Version 2.10.0-14.0.dev Merge commit '552a8b1a0cc0acb8b924230533ff81d4b08987c9' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml index f7c4d16..760e76a 100644 --- a/pkg/_fe_analyzer_shared/pubspec.yaml +++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@ name: _fe_analyzer_shared -version: 6.0.0 +version: 7.0.0 description: Logic that is shared between the front_end and analyzer packages. homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart index f0a7bba..d85e724 100644 --- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart +++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -7,13 +7,8 @@ import 'package:analysis_server/protocol/protocol_generated.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:analyzer/dart/ast/ast_factory.dart'; -import 'package:analyzer/dart/ast/token.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/dart/ast/ast_factory.dart'; -import 'package:analyzer/src/dart/ast/token.dart'; -import 'package:analyzer/src/dart/resolver/scope.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element; import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart'; @@ -243,24 +238,12 @@ /// name as in the original source. List<ImportedElements> _filterImportedElements( List<ImportedElements> originalList) { - var libraryElement = libraryResult.libraryElement; - var libraryScope = libraryElement.scope; - AstFactory factory = AstFactoryImpl(); var filteredList = <ImportedElements>[]; for (var elements in originalList) { var originalElements = elements.elements; var filteredElements = originalElements.toList(); for (var name in originalElements) { - Identifier identifier = factory - .simpleIdentifier(StringToken(TokenType.IDENTIFIER, name, -1)); - if (elements.prefix.isNotEmpty) { - var prefix = factory.simpleIdentifier( - StringToken(TokenType.IDENTIFIER, elements.prefix, -1)); - Token period = SimpleToken(TokenType.PERIOD, -1); - identifier = factory.prefixedIdentifier(prefix, period, identifier); - } - var element = libraryScope.lookupIdentifier(identifier); - if (element != null) { + if (_hasElement(elements.prefix, name)) { filteredElements.remove(name); } } @@ -340,6 +323,22 @@ return context.split(relativeFile).join('/'); } + bool _hasElement(String prefix, String name) { + var scope = libraryResult.libraryElement.scope; + + if (prefix.isNotEmpty) { + var prefixElement = scope.lookup2(prefix).getter; + if (prefixElement is PrefixElement) { + scope = prefixElement.scope; + } else { + return false; + } + } + + var lookupResult = scope.lookup2(name); + return lookupResult.getter != null || lookupResult.setter != null; + } + /// Return `true` if the given [import] matches the given specification of /// [importedElements]. They will match if they import the same library using /// the same prefix.
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart index 8a51410..1e39e30 100644 --- a/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart +++ b/pkg/analysis_server/test/services/completion/dart/relevance/named_argument_relevance_test.dart
@@ -2,7 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/src/test_utilities/package_mixin.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; @@ -16,22 +15,23 @@ } @reflectiveTest -class NamedArgumentRelevanceTest extends CompletionRelevanceTest - with PackageMixin { - @override - Map<String, List<Folder>> packageMap = {}; - +class NamedArgumentRelevanceTest extends CompletionRelevanceTest { @override void setUp() { super.setUp(); + + var metaPath = '/.pub-cache/meta'; + PackagesContent.addMetaPackageFiles( + getFolder(metaPath), + ); + newFile('$projectPath/.packages', content: ''' -meta:${toUri('/.pub-cache/meta/lib')} +meta:${toUri('$metaPath/lib')} project:${toUri('$projectPath/lib')} '''); } Future<void> test_requiredAnnotation() async { - addMetaPackage(); await addTestFile(''' import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md index 50ac6e8..7d6d0e3 100644 --- a/pkg/analyzer/CHANGELOG.md +++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,6 @@ +## 0.39.17 +* Depend on cli_util 0.2.0. + ## 0.39.16 * Added `TypeVisitorWithArgument` and `DartType.acceptWithArgument`. * Bumped the analyzer's SDK requirement to `>=2.7.0`, so that extension methods
diff --git a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart index c8b7f64..40f9dcf 100644 --- a/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart +++ b/pkg/analyzer/lib/src/dart/resolver/ast_rewrite.dart
@@ -8,7 +8,6 @@ import 'package:analyzer/dart/element/scope.dart'; import 'package:analyzer/error/listener.dart'; import 'package:analyzer/src/dart/ast/utilities.dart'; -import 'package:analyzer/src/dart/resolver/scope.dart'; import 'package:analyzer/src/error/codes.dart'; /// Helper for [MethodInvocation]s into [InstanceCreationExpression] to support @@ -33,7 +32,7 @@ // This isn't a constructor invocation because it's in a cascade. return node; } - Element element = nameScope.lookupIdentifier(methodName); + Element element = nameScope.lookup2(methodName.name).getter; if (element is ClassElement) { TypeName typeName = astFactory.typeName(methodName, node.typeArguments); ConstructorName constructorName = @@ -57,7 +56,7 @@ // This isn't a constructor invocation because a null aware operator is // being used. } - Element element = nameScope.lookupIdentifier(target); + Element element = nameScope.lookup2(target.name).getter; if (element is ClassElement) { // Possible case: C.n() var constructorElement = element.getNamedConstructor(methodName.name); @@ -82,11 +81,7 @@ } } else if (element is PrefixElement) { // Possible cases: p.C() or p.C<>() - Identifier identifier = astFactory.prefixedIdentifier( - astFactory.simpleIdentifier(target.token), - null, - astFactory.simpleIdentifier(methodName.token)); - Element prefixedElement = nameScope.lookupIdentifier(identifier); + Element prefixedElement = element.scope.lookup2(methodName.name).getter; if (prefixedElement is ClassElement) { TypeName typeName = astFactory.typeName( astFactory.prefixedIdentifier(target, node.operator, methodName), @@ -111,10 +106,11 @@ } } else if (target is PrefixedIdentifier) { // Possible case: p.C.n() - Element prefixElement = nameScope.lookupIdentifier(target.prefix); + Element prefixElement = nameScope.lookup2(target.prefix.name).getter; target.prefix.staticElement = prefixElement; if (prefixElement is PrefixElement) { - Element element = nameScope.lookupIdentifier(target); + Element element = + prefixElement.scope.lookup2(target.identifier.name).getter; if (element is ClassElement) { var constructorElement = element.getNamedConstructor(methodName.name); if (constructorElement != null) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart index 2787d4b..0eebe01 100644 --- a/pkg/analyzer/lib/src/dart/resolver/scope.dart +++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -449,26 +449,4 @@ } throw StateError('Can only be used in a LibraryScope.'); } - - // TODO(scheglov) check if it might be inlined - Element lookupIdentifier(Identifier identifier) { - if (identifier is SimpleIdentifier) { - var result = lookup2(identifier.name); - return result.getter ?? result.setter; - } else { - var prefixedIdentifier = identifier as PrefixedIdentifier; - - var prefixIdentifier = prefixedIdentifier.prefix; - var prefixName = prefixIdentifier.name; - var prefixElement = lookup2(prefixName).getter; - prefixIdentifier.staticElement = prefixElement; - - if (prefixElement is PrefixElement) { - var name = prefixedIdentifier.identifier.name; - var result = prefixElement.scope.lookup2(name); - return result.getter ?? result.setter; - } - } - return null; - } }
diff --git a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart index f28b925..efefa53 100644 --- a/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart +++ b/pkg/analyzer/lib/src/error/constructor_fields_verifier.dart
@@ -80,7 +80,7 @@ _fieldMap.forEach((FieldElement field, _InitState state) { if (state != _InitState.notInit) return; if (field.isLate) return; - if (field.isAbstract) return; + if (field.isAbstract || field.isExternal) return; if (field.isFinal) { notInitFinalFields.add(field);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 4eb6d7d..056efeb 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3566,7 +3566,7 @@ for (var field in fields.variables) { var fieldElement = field.declaredElement as FieldElement; - if (fieldElement.isAbstract) continue; + if (fieldElement.isAbstract || fieldElement.isExternal) continue; if (field.initializer != null) continue; var type = fieldElement.type; @@ -3603,6 +3603,11 @@ return; } + var parent = node.parent; + if (parent is FieldDeclaration && parent.externalKeyword != null) { + return; + } + if (node.type == null) { return; }
diff --git a/pkg/analyzer/lib/src/test_utilities/package_mixin.dart b/pkg/analyzer/lib/src/test_utilities/package_mixin.dart index 7889ece..9294d4e 100644 --- a/pkg/analyzer/lib/src/test_utilities/package_mixin.dart +++ b/pkg/analyzer/lib/src/test_utilities/package_mixin.dart
@@ -3,41 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart'; - -/// A mixin for test classes that provides support for creating packages. -mixin PackageMixin implements ResourceProviderMixin { - /// Return the map from package names to lists of folders that is used to - /// resolve 'package:' URIs. - Map<String, List<Folder>> get packageMap; - - /// Create a fake 'js' package that can be used by tests. - void addJsPackage() { - var rootFolder = getFolder('/.pub-cache/js'); - PackagesContent.addJsPackageFiles(rootFolder); - addPubPackage('js'); - } - - /// Create a fake 'meta' package that can be used by tests. - void addMetaPackage() { - var rootFolder = getFolder('/.pub-cache/meta'); - PackagesContent.addMetaPackageFiles(rootFolder); - addPubPackage('meta'); - } - - /// Return a newly created directory in which the contents of a pub package - /// with the given [packageName] can be written. The package will be added to - /// the package map so that the package can be referenced from the code being - /// analyzed. - Folder addPubPackage(String packageName) { - // TODO(brianwilkerson) Consider renaming this to `addPackage` and passing - // in a `PackageStyle` (pub, bazel, gn, build, plain) in order to support - // creating other styles of packages. - Folder lib = getFolder('/.pub-cache/$packageName/lib'); - packageMap[packageName] = [lib]; - return lib; - } -} /// Helper for creating mock packages. class PackagesContent {
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml index becd0e8..be78fcc 100644 --- a/pkg/analyzer/pubspec.yaml +++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@ name: analyzer -version: 0.39.16 +version: 0.39.17 description: This package provides a library that performs static analysis of Dart code. homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer @@ -7,7 +7,7 @@ sdk: '>=2.7.0 <3.0.0' dependencies: - _fe_analyzer_shared: ^6.0.0 + _fe_analyzer_shared: ^7.0.0 args: ^1.0.0 charcode: ^1.1.0 cli_util: '>=0.1.4 <0.3.0'
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart index 779b01d..9fca7de 100644 --- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -55,8 +55,9 @@ _assertNoLinkedCycles(); } - void _assertContainsLinkedCycle(Set<String> expected, + void _assertContainsLinkedCycle(Set<String> expectedPosix, {bool andClear = false}) { + var expected = expectedPosix.map(convertPath).toSet(); expect(_linkedCycles, contains(unorderedEquals(expected))); if (andClear) { _linkedCycles.clear();
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart index fc35f34..7f20112 100644 --- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart +++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -577,6 +577,21 @@ '''); } + test_external_field_covariant_inheritance() async { + await assertNoErrorsInCode(''' +abstract class A { + external covariant num x; +} +abstract class B implements A { + void set x(Object value); // Implicitly covariant +} +abstract class C implements B { + int get x; + void set x(int value); // Ok because covariant +} +'''); + } + test_getter_overrides_abstract_field_covariant_invalid() async { await assertErrorsInCode(''' abstract class A { @@ -652,6 +667,56 @@ '''); } + test_getter_overrides_external_field_covariant_invalid() async { + await assertErrorsInCode(''' +class A { + external covariant int x; +} +abstract class B implements A { + num get x; + void set x(num value); +} +''', [ + error(CompileTimeErrorCode.INVALID_OVERRIDE, 82, 1), + ]); + } + + test_getter_overrides_external_field_covariant_valid() async { + await assertNoErrorsInCode(''' +class A { + external covariant num x; +} +abstract class B implements A { + int get x; +} +'''); + } + + test_getter_overrides_external_field_invalid() async { + await assertErrorsInCode(''' +class A { + external int x; +} +abstract class B implements A { + num get x; + void set x(num value); +} +''', [ + error(CompileTimeErrorCode.INVALID_OVERRIDE, 72, 1), + ]); + } + + test_getter_overrides_external_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external num x; +} +abstract class B implements A { + int get x; +} +'''); + } + test_method_parameter_functionTyped_optOut_extends_optIn() async { newFile('$testPackageLibPath/a.dart', content: r''' abstract class A { @@ -798,6 +863,43 @@ '''); } + test_setter_overrides_external_field_covariant_valid() async { + await assertNoErrorsInCode(''' +class A { + external covariant num x; +} +abstract class B implements A { + int get x; + void set x(int value); +} +'''); + } + + test_setter_overrides_external_field_invalid() async { + await assertErrorsInCode(''' +class A { + external num x; +} +abstract class B implements A { + int get x; + void set x(int value); +} +''', [ + error(CompileTimeErrorCode.INVALID_OVERRIDE, 86, 1), + ]); + } + + test_setter_overrides_external_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external int x; +} +abstract class B implements A { + void set x(num value); +} +'''); + } + test_viaLegacy_class() async { newFile('$testPackageLibPath/a.dart', content: r''' class A1 {
diff --git a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_instance_field_test.dart b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_instance_field_test.dart index 08e6965..7ade83f 100644 --- a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_instance_field_test.dart +++ b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_instance_field_test.dart
@@ -87,6 +87,23 @@ '''); } + test_external_field_non_nullable() async { + await assertNoErrorsInCode(''' +class A { + external int x; +} +'''); + } + + test_external_field_non_nullable_with_constructor() async { + await assertNoErrorsInCode(''' +class A { + external int x; + A(); +} +'''); + } + test_fieldFormal() async { await assertNoErrorsInCode(''' class A {
diff --git a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_variable_test.dart index d7d101e..bb1f2d1 100644 --- a/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_variable_test.dart +++ b/pkg/analyzer/test/src/diagnostics/not_initialized_non_nullable_variable_test.dart
@@ -16,6 +16,14 @@ @reflectiveTest class NotInitializedNonNullableVariableTest extends PubPackageResolutionTest with WithNullSafetyMixin { + test_external_static_field_non_nullable() async { + await assertNoErrorsInCode(''' +class A { + external static int x; +} +'''); + } + test_staticField_futureOr_questionArgument_none() async { await assertNoErrorsInCode(''' import 'dart:async';
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart index 65b9468..eaa394f 100644 --- a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart +++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -374,6 +374,24 @@ '''); } + test_get_from_external_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external int x; +} +int f(A a) => a.x; +'''); + } + + test_get_from_external_static_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external static int x; +} +int f() => A.x; +'''); + } + @override @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/42957') test_typeLiteral_conditionalAccess() {
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart index d5c09b8..3fbb7c1 100644 --- a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart +++ b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
@@ -153,4 +153,26 @@ } '''); } + + test_set_external_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external int x; +} +void f(A a, int x) { + a.x = x; +} +'''); + } + + test_set_external_static_field_valid() async { + await assertNoErrorsInCode(''' +class A { + external static int x; +} +void f(int x) { + A.x = x; +} +'''); + } }
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md index 245ac92..a3f0493 100644 --- a/pkg/dartfix/README.md +++ b/pkg/dartfix/README.md
@@ -73,10 +73,10 @@ If no issue exists for the fix, [create a GitHub issue.][new issue] [dartfix]: https://pub.dev/packages/dartfix -[dartfmt]: https://www.dartlang.org/tools/dartfmt +[dartfmt]: https://dart.dev/tools/dartfmt [added in Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15 [features added to Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15 -[globally install]: https://www.dartlang.org/tools/pub/cmd/pub-global +[globally install]: https://dart.dev/tools/pub/cmd/pub-global [new issue]: https://github.com/dart-lang/sdk/issues/new?title=dartfix%20request%3A%20%3CSUMMARIZE%20REQUEST%20HERE%3E [dartfix issues]: https://github.com/dart-lang/sdk/issues?q=is%3Aissue+is%3Aopen+label%3Aanalyzer-dartfix -[PATH]: https://www.dartlang.org/tools/pub/cmd/pub-global#running-a-script-from-your-path +[PATH]: https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart index 14ddeb8..f1c0e20 100644 --- a/pkg/vm/lib/transformations/type_flow/transformer.dart +++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -705,6 +705,12 @@ isSetter: m.isSetter); addUsedMember(m.forwardingStubInterfaceTarget); } + if (m.memberSignatureOrigin != null) { + m.memberSignatureOrigin = fieldMorpher.adjustInstanceCallTarget( + m.memberSignatureOrigin, + isSetter: m.isSetter); + addUsedMember(m.memberSignatureOrigin); + } } else if (m is Constructor) { func = m.function; } else {
diff --git a/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java b/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java index f335d5c..c44b31d 100644 --- a/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java +++ b/pkg/vm_service/java/src/org/dartlang/vm/service/VmServiceBase.java
@@ -313,7 +313,7 @@ /** * Invoke a specific service protocol extension method. * <p> - * See https://api.dartlang.org/stable/dart-developer/dart-developer-library.html. + * See https://api.dart.dev/stable/dart-developer/dart-developer-library.html. */ public void callServiceExtension(String isolateId, String method, ServiceExtensionConsumer consumer) { JsonObject params = new JsonObject(); @@ -324,7 +324,7 @@ /** * Invoke a specific service protocol extension method. * <p> - * See https://api.dartlang.org/stable/dart-developer/dart-developer-library.html. + * See https://api.dart.dev/stable/dart-developer/dart-developer-library.html. */ public void callServiceExtension(String isolateId, String method, JsonObject params, ServiceExtensionConsumer consumer) { params.addProperty("isolateId", isolateId);
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart index c317c46..9fd8aba 100644 --- a/pkg/vm_service/lib/src/vm_service.dart +++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -2005,7 +2005,7 @@ /// Invoke a specific service protocol extension method. /// - /// See https://api.dartlang.org/stable/dart-developer/dart-developer-library.html. + /// See https://api.dart.dev/stable/dart-developer/dart-developer-library.html. @override Future<Response> callServiceExtension(String method, {String isolateId, Map args}) {
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart index 02ae7e1..1553861 100644 --- a/pkg/vm_service/tool/dart/generate_dart.dart +++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -77,7 +77,7 @@ /// Invoke a specific service protocol extension method. /// - /// See https://api.dartlang.org/stable/dart-developer/dart-developer-library.html. + /// See https://api.dart.dev/stable/dart-developer/dart-developer-library.html. @override Future<Response> callServiceExtension(String method, { String isolateId,
diff --git a/pkg/vm_service/tool/java/generate_java.dart b/pkg/vm_service/tool/java/generate_java.dart index 6254446..675ce5b 100644 --- a/pkg/vm_service/tool/java/generate_java.dart +++ b/pkg/vm_service/tool/java/generate_java.dart
@@ -36,7 +36,7 @@ </pre> where <strong>some-port</strong> is a port number of your choice which this client will use to communicate with the Dart VM. -See https://www.dartlang.org/tools/dart-vm/ for more details. +See https://dart.dev/tools/dart-vm for more details. Once the VM is running, instantiate a new {@link VmService} to connect to that VM via {@link VmService#connect(String)} or {@link VmService#localConnect(int)}.
diff --git a/samples/ffi/sqlite/.gitignore b/samples/ffi/sqlite/.gitignore index 61f2cb6..7a6bc2e 100644 --- a/samples/ffi/sqlite/.gitignore +++ b/samples/ffi/sqlite/.gitignore
@@ -4,4 +4,4 @@ .vscode pubspec.lock test.db -test.db-journal +test.db-journal \ No newline at end of file
diff --git a/samples/ffi/sqlite/lib/src/bindings/bindings.dart b/samples/ffi/sqlite/lib/src/bindings/bindings.dart new file mode 100644 index 0000000..0271506 --- /dev/null +++ b/samples/ffi/sqlite/lib/src/bindings/bindings.dart
@@ -0,0 +1,394 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:ffi"; +import "package:ffi/ffi.dart"; + +import "../ffi/dylib_utils.dart"; + +import "signatures.dart"; +import "types.dart"; + +class _SQLiteBindings { + DynamicLibrary sqlite; + + /// Opening A New Database Connection + /// + /// ^These routines open an SQLite database file as specified by the + /// filename argument. ^The filename argument is interpreted as UTF-8 for + /// sqlite3_open() and sqlite3_open_v2() and as UTF-16 in the native byte + /// order for sqlite3_open16(). ^(A database connection handle is usually + /// returned in *ppDb, even if an error occurs. The only exception is that + /// if SQLite is unable to allocate memory to hold the sqlite3 object, + /// a NULL will be written into *ppDb instead of a pointer to the sqlite3 + /// object.)^ ^(If the database is opened (and/or created) successfully, then + /// [SQLITE_OK] is returned. Otherwise an error code is returned.)^ ^The + /// [sqlite3_errmsg] or sqlite3_errmsg16() routines can be used to obtain + /// an English language description of the error following a failure of any + /// of the sqlite3_open() routines. + int Function(Pointer<Utf8> filename, Pointer<Pointer<Database>> databaseOut, + int flags, Pointer<Utf8> vfs) sqlite3_open_v2; + + int Function(Pointer<Database> database) sqlite3_close_v2; + + /// Compiling An SQL Statement + /// + /// To execute an SQL query, it must first be compiled into a byte-code + /// program using one of these routines. + /// + /// The first argument, "db", is a database connection obtained from a + /// prior successful call to sqlite3_open, [sqlite3_open_v2] or + /// sqlite3_open16. The database connection must not have been closed. + /// + /// The second argument, "zSql", is the statement to be compiled, encoded + /// as either UTF-8 or UTF-16. The sqlite3_prepare() and sqlite3_prepare_v2() + /// interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2() + /// use UTF-16. + /// + /// ^If the nByte argument is less than zero, then zSql is read up to the + /// first zero terminator. ^If nByte is non-negative, then it is the maximum + /// number of bytes read from zSql. ^When nByte is non-negative, the + /// zSql string ends at either the first '\000' or '\u0000' character or + /// the nByte-th byte, whichever comes first. If the caller knows + /// that the supplied string is nul-terminated, then there is a small + /// performance advantage to be gained by passing an nByte parameter that + /// is equal to the number of bytes in the input string <i>including</i> + /// the nul-terminator bytes. + /// + /// ^If pzTail is not NULL then *pzTail is made to point to the first byte + /// past the end of the first SQL statement in zSql. These routines only + /// compile the first statement in zSql, so *pzTail is left pointing to + /// what remains uncompiled. + /// + /// ^*ppStmt is left pointing to a compiled prepared statement that can be + /// executed using sqlite3_step. ^If there is an error, *ppStmt is set + /// to NULL. ^If the input text contains no SQL (if the input is an empty + /// string or a comment) then *ppStmt is set to NULL. + /// The calling procedure is responsible for deleting the compiled + /// SQL statement using [sqlite3_finalize] after it has finished with it. + /// ppStmt may not be NULL. + /// + /// ^On success, the sqlite3_prepare family of routines return [SQLITE_OK]; + /// otherwise an error code is returned. + /// + /// The sqlite3_prepare_v2() and sqlite3_prepare16_v2() interfaces are + /// recommended for all new programs. The two older interfaces are retained + /// for backwards compatibility, but their use is discouraged. + /// ^In the "v2" interfaces, the prepared statement + /// that is returned (the sqlite3_stmt object) contains a copy of the + /// original SQL text. This causes the [sqlite3_step] interface to + /// behave differently in three ways: + int Function( + Pointer<Database> database, + Pointer<Utf8> query, + int nbytes, + Pointer<Pointer<Statement>> statementOut, + Pointer<Pointer<Utf8>> tail) sqlite3_prepare_v2; + + /// Evaluate An SQL Statement + /// + /// After a prepared statement has been prepared using either + /// [sqlite3_prepare_v2] or sqlite3_prepare16_v2() or one of the legacy + /// interfaces sqlite3_prepare() or sqlite3_prepare16(), this function + /// must be called one or more times to evaluate the statement. + /// + /// The details of the behavior of the sqlite3_step() interface depend + /// on whether the statement was prepared using the newer "v2" interface + /// [sqlite3_prepare_v2] and sqlite3_prepare16_v2() or the older legacy + /// interface sqlite3_prepare() and sqlite3_prepare16(). The use of the + /// new "v2" interface is recommended for new applications but the legacy + /// interface will continue to be supported. + /// + /// ^In the legacy interface, the return value will be either [SQLITE_BUSY], + /// [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. + /// ^With the "v2" interface, any of the other [result codes] or + /// [extended result codes] might be returned as well. + /// + /// ^[SQLITE_BUSY] means that the database engine was unable to acquire the + /// database locks it needs to do its job. ^If the statement is a [COMMIT] + /// or occurs outside of an explicit transaction, then you can retry the + /// statement. If the statement is not a [COMMIT] and occurs within an + /// explicit transaction then you should rollback the transaction before + /// continuing. + /// + /// ^[SQLITE_DONE] means that the statement has finished executing + /// successfully. sqlite3_step() should not be called again on this virtual + /// machine without first calling [sqlite3_reset()] to reset the virtual + /// machine back to its initial state. + /// + /// ^If the SQL statement being executed returns any data, then [SQLITE_ROW] + /// is returned each time a new row of data is ready for processing by the + /// caller. The values may be accessed using the [column access functions]. + /// sqlite3_step() is called again to retrieve the next row of data. + /// + /// ^[SQLITE_ERROR] means that a run-time error (such as a constraint + /// violation) has occurred. sqlite3_step() should not be called again on + /// the VM. More information may be found by calling [sqlite3_errmsg()]. + /// ^With the legacy interface, a more specific error code (for example, + /// [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) + /// can be obtained by calling [sqlite3_reset()] on the + /// prepared statement. ^In the "v2" interface, + /// the more specific error code is returned directly by sqlite3_step(). + /// + /// [SQLITE_MISUSE] means that the this routine was called inappropriately. + /// Perhaps it was called on a prepared statement that has + /// already been [sqlite3_finalize | finalized] or on one that had + /// previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could + /// be the case that the same database connection is being used by two or + /// more threads at the same moment in time. + /// + /// For all versions of SQLite up to and including 3.6.23.1, a call to + /// [sqlite3_reset] was required after sqlite3_step() returned anything + /// other than [Errors.SQLITE_ROW] before any subsequent invocation of + /// sqlite3_step(). Failure to reset the prepared statement using + /// [sqlite3_reset()] would result in an [Errors.SQLITE_MISUSE] return from + /// sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began + /// calling [sqlite3_reset] automatically in this circumstance rather + /// than returning [Errors.SQLITE_MISUSE]. This is not considered a + /// compatibility break because any application that ever receives an + /// [Errors.SQLITE_MISUSE] error is broken by definition. The + /// [SQLITE_OMIT_AUTORESET] compile-time option + /// can be used to restore the legacy behavior. + /// + /// <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step() + /// API always returns a generic error code, [SQLITE_ERROR], following any + /// error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call + /// [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the + /// specific [error codes] that better describes the error. + /// We admit that this is a goofy design. The problem has been fixed + /// with the "v2" interface. If you prepare all of your SQL statements + /// using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] instead + /// of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, + /// then the more specific [error codes] are returned directly + /// by sqlite3_step(). The use of the "v2" interface is recommended. + int Function(Pointer<Statement> statement) sqlite3_step; + + /// CAPI3REF: Reset A Prepared Statement Object + /// + /// The sqlite3_reset() function is called to reset a prepared statement + /// object back to its initial state, ready to be re-executed. + /// ^Any SQL statement variables that had values bound to them using + /// the sqlite3_bind_blob | sqlite3_bind_*() API retain their values. + /// Use sqlite3_clear_bindings() to reset the bindings. + /// + /// ^The [sqlite3_reset] interface resets the prepared statement S + /// back to the beginning of its program. + /// + /// ^If the most recent call to [sqlite3_step] for the + /// prepared statement S returned [Errors.SQLITE_ROW] or [Errors.SQLITE_DONE], + /// or if [sqlite3_step] has never before been called on S, + /// then [sqlite3_reset] returns [Errors.SQLITE_OK]. + /// + /// ^If the most recent call to [sqlite3_step(S)] for the + /// prepared statement S indicated an error, then + /// [sqlite3_reset] returns an appropriate [Errors]. + /// + /// ^The [sqlite3_reset] interface does not change the values + int Function(Pointer<Statement> statement) sqlite3_reset; + + /// Destroy A Prepared Statement Object + /// + /// ^The sqlite3_finalize() function is called to delete a prepared statement. + /// ^If the most recent evaluation of the statement encountered no errors + /// or if the statement is never been evaluated, then sqlite3_finalize() + /// returns SQLITE_OK. ^If the most recent evaluation of statement S failed, + /// then sqlite3_finalize(S) returns the appropriate error code or extended + /// error code. + /// + /// ^The sqlite3_finalize(S) routine can be called at any point during + /// the life cycle of prepared statement S: + /// before statement S is ever evaluated, after + /// one or more calls to [sqlite3_reset], or after any call + /// to [sqlite3_step] regardless of whether or not the statement has + /// completed execution. + /// + /// ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. + /// + /// The application must finalize every prepared statement in order to avoid + /// resource leaks. It is a grievous error for the application to try to use + /// a prepared statement after it has been finalized. Any use of a prepared + /// statement after it has been finalized can result in undefined and + /// undesirable behavior such as segfaults and heap corruption. + int Function(Pointer<Statement> statement) sqlite3_finalize; + + /// Number Of Columns In A Result Set + /// + /// ^Return the number of columns in the result set returned by the + /// prepared statement. ^This routine returns 0 if pStmt is an SQL + /// statement that does not return data (for example an [UPDATE]). + int Function(Pointer<Statement> statement) sqlite3_column_count; + + /// Column Names In A Result Set + /// + /// ^These routines return the name assigned to a particular column + /// in the result set of a SELECT statement. ^The sqlite3_column_name() + /// interface returns a pointer to a zero-terminated UTF-8 string + /// and sqlite3_column_name16() returns a pointer to a zero-terminated + /// UTF-16 string. ^The first parameter is the prepared statement + /// that implements the SELECT statement. ^The second parameter is the + /// column number. ^The leftmost column is number 0. + /// + /// ^The returned string pointer is valid until either the prepared statement + /// is destroyed by [sqlite3_finalize] or until the statement is automatically + /// reprepared by the first call to [sqlite3_step] for a particular run + /// or until the next call to + /// sqlite3_column_name() or sqlite3_column_name16() on the same column. + /// + /// ^If sqlite3_malloc() fails during the processing of either routine + /// (for example during a conversion from UTF-8 to UTF-16) then a + /// NULL pointer is returned. + /// + /// ^The name of a result column is the value of the "AS" clause for + /// that column, if there is an AS clause. If there is no AS clause + /// then the name of the column is unspecified and may change from + Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_name; + + /// CAPI3REF: Declared Datatype Of A Query Result + /// + /// ^(The first parameter is a prepared statement. + /// If this statement is a SELECT statement and the Nth column of the + /// returned result set of that SELECT is a table column (not an + /// expression or subquery) then the declared type of the table + /// column is returned.)^ ^If the Nth column of the result set is an + /// expression or subquery, then a NULL pointer is returned. + /// ^The returned string is always UTF-8 encoded. + /// + /// ^(For example, given the database schema: + /// + /// CREATE TABLE t1(c1 VARIANT); + /// + /// and the following statement to be compiled: + /// + /// SELECT c1 + 1, c1 FROM t1; + /// + /// this routine would return the string "VARIANT" for the second result + /// column (i==1), and a NULL pointer for the first result column (i==0).)^ + /// + /// ^SQLite uses dynamic run-time typing. ^So just because a column + /// is declared to contain a particular type does not mean that the + /// data stored in that column is of the declared type. SQLite is + /// strongly typed, but the typing is dynamic not static. ^Type + /// is associated with individual values, not with the containers + /// used to hold those values. + Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_decltype; + + int Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_type; + + Pointer<Value> Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_value; + + double Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_double; + + int Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_int; + + Pointer<Utf8> Function(Pointer<Statement> statement, int columnIndex) + sqlite3_column_text; + + /// The sqlite3_errstr() interface returns the English-language text that + /// describes the result code, as UTF-8. Memory to hold the error message + /// string is managed internally and must not be freed by the application. + Pointer<Utf8> Function(int code) sqlite3_errstr; + + /// Error Codes And Messages + /// + /// ^The sqlite3_errcode() interface returns the numeric [result code] or + /// [extended result code] for the most recent failed sqlite3_* API call + /// associated with a [database connection]. If a prior API call failed + /// but the most recent API call succeeded, the return value from + /// sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode() + /// interface is the same except that it always returns the + /// [extended result code] even when extended result codes are + /// disabled. + /// + /// ^The sqlite3_errmsg() and sqlite3_errmsg16() return English-language + /// text that describes the error, as either UTF-8 or UTF-16 respectively. + /// ^(Memory to hold the error message string is managed internally. + /// The application does not need to worry about freeing the result. + /// However, the error string might be overwritten or deallocated by + /// subsequent calls to other SQLite interface functions.)^ + /// + /// When the serialized [threading mode] is in use, it might be the + /// case that a second error occurs on a separate thread in between + /// the time of the first error and the call to these interfaces. + /// When that happens, the second error will be reported since these + /// interfaces always report the most recent result. To avoid + /// this, each thread can obtain exclusive use of the [database connection] D + /// by invoking [sqlite3_mutex_enter]([sqlite3_db_mutex](D)) before beginning + /// to use D and invoking [sqlite3_mutex_leave]([sqlite3_db_mutex](D)) after + /// all calls to the interfaces listed here are completed. + /// + /// If an interface fails with SQLITE_MISUSE, that means the interface + /// was invoked incorrectly by the application. In that case, the + /// error code and message may or may not be set. + Pointer<Utf8> Function(Pointer<Database> database) sqlite3_errmsg; + + _SQLiteBindings() { + sqlite = dlopenPlatformSpecific("sqlite3"); + sqlite3_open_v2 = sqlite + .lookup<NativeFunction<sqlite3_open_v2_native_t>>("sqlite3_open_v2") + .asFunction(); + sqlite3_close_v2 = sqlite + .lookup<NativeFunction<sqlite3_close_v2_native_t>>("sqlite3_close_v2") + .asFunction(); + sqlite3_prepare_v2 = sqlite + .lookup<NativeFunction<sqlite3_prepare_v2_native_t>>( + "sqlite3_prepare_v2") + .asFunction(); + sqlite3_step = sqlite + .lookup<NativeFunction<sqlite3_step_native_t>>("sqlite3_step") + .asFunction(); + sqlite3_reset = sqlite + .lookup<NativeFunction<sqlite3_reset_native_t>>("sqlite3_reset") + .asFunction(); + sqlite3_finalize = sqlite + .lookup<NativeFunction<sqlite3_finalize_native_t>>("sqlite3_finalize") + .asFunction(); + sqlite3_errstr = sqlite + .lookup<NativeFunction<sqlite3_errstr_native_t>>("sqlite3_errstr") + .asFunction(); + sqlite3_errmsg = sqlite + .lookup<NativeFunction<sqlite3_errmsg_native_t>>("sqlite3_errmsg") + .asFunction(); + sqlite3_column_count = sqlite + .lookup<NativeFunction<sqlite3_column_count_native_t>>( + "sqlite3_column_count") + .asFunction(); + sqlite3_column_name = sqlite + .lookup<NativeFunction<sqlite3_column_name_native_t>>( + "sqlite3_column_name") + .asFunction(); + sqlite3_column_decltype = sqlite + .lookup<NativeFunction<sqlite3_column_decltype_native_t>>( + "sqlite3_column_decltype") + .asFunction(); + sqlite3_column_type = sqlite + .lookup<NativeFunction<sqlite3_column_type_native_t>>( + "sqlite3_column_type") + .asFunction(); + sqlite3_column_value = sqlite + .lookup<NativeFunction<sqlite3_column_value_native_t>>( + "sqlite3_column_value") + .asFunction(); + sqlite3_column_double = sqlite + .lookup<NativeFunction<sqlite3_column_double_native_t>>( + "sqlite3_column_double") + .asFunction(); + sqlite3_column_int = sqlite + .lookup<NativeFunction<sqlite3_column_int_native_t>>( + "sqlite3_column_int") + .asFunction(); + sqlite3_column_text = sqlite + .lookup<NativeFunction<sqlite3_column_text_native_t>>( + "sqlite3_column_text") + .asFunction(); + } +} + +_SQLiteBindings _cachedBindings; +_SQLiteBindings get bindings => _cachedBindings ??= _SQLiteBindings();
diff --git a/samples/ffi/sqlite/lib/src/bindings/constants.dart b/samples/ffi/sqlite/lib/src/bindings/constants.dart new file mode 100644 index 0000000..71aa82e --- /dev/null +++ b/samples/ffi/sqlite/lib/src/bindings/constants.dart
@@ -0,0 +1,182 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// Result Codes +/// +/// Many SQLite functions return an integer result code from the set shown +/// here in order to indicates success or failure. +/// +/// New error codes may be added in future versions of SQLite. +/// +/// See also: SQLITE_IOERR_READ | extended result codes, +/// sqlite3_vtab_on_conflict() SQLITE_ROLLBACK | result codes. +class Errors { + /// Successful result + static const int SQLITE_OK = 0; + + /// Generic error + static const int SQLITE_ERROR = 1; + + /// Internal logic error in SQLite + static const int SQLITE_INTERNAL = 2; + + /// Access permission denied + static const int SQLITE_PERM = 3; + + /// Callback routine requested an abort + static const int SQLITE_ABORT = 4; + + /// The database file is locked + static const int SQLITE_BUSY = 5; + + /// A table in the database is locked + static const int SQLITE_LOCKED = 6; + + /// A malloc() failed + static const int SQLITE_NOMEM = 7; + + /// Attempt to write a readonly database + static const int SQLITE_READONLY = 8; + + /// Operation terminated by sqlite3_interrupt() + static const int SQLITE_INTERRUPT = 9; + + /// Some kind of disk I/O error occurred + static const int SQLITE_IOERR = 10; + + /// The database disk image is malformed + static const int SQLITE_CORRUPT = 11; + + /// Unknown opcode in sqlite3_file_control() + static const int SQLITE_NOTFOUND = 12; + + /// Insertion failed because database is full + static const int SQLITE_FULL = 13; + + /// Unable to open the database file + static const int SQLITE_CANTOPEN = 14; + + /// Database lock protocol error + static const int SQLITE_PROTOCOL = 15; + + /// Internal use only + static const int SQLITE_EMPTY = 16; + + /// The database schema changed + static const int SQLITE_SCHEMA = 17; + + /// String or BLOB exceeds size limit + static const int SQLITE_TOOBIG = 18; + + /// Abort due to constraint violation + static const int SQLITE_CONSTRAINT = 19; + + /// Data type mismatch + static const int SQLITE_MISMATCH = 20; + + /// Library used incorrectly + static const int SQLITE_MISUSE = 21; + + /// Uses OS features not supported on host + static const int SQLITE_NOLFS = 22; + + /// Authorization denied + static const int SQLITE_AUTH = 23; + + /// Not used + static const int SQLITE_FORMAT = 24; + + /// 2nd parameter to sqlite3_bind out of range + static const int SQLITE_RANGE = 25; + + /// File opened that is not a database file + static const int SQLITE_NOTADB = 26; + + /// Notifications from sqlite3_log() + static const int SQLITE_NOTICE = 27; + + /// Warnings from sqlite3_log() + static const int SQLITE_WARNING = 28; + + /// sqlite3_step() has another row ready + static const int SQLITE_ROW = 100; + + /// sqlite3_step() has finished executing + static const int SQLITE_DONE = 101; +} + +/// Flags For File Open Operations +/// +/// These bit values are intended for use in the +/// 3rd parameter to the [sqlite3_open_v2()] interface and +/// in the 4th parameter to the [sqlite3_vfs.xOpen] method. +class Flags { + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_READONLY = 0x00000001; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_READWRITE = 0x00000002; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_CREATE = 0x00000004; + + /// VFS only + static const int SQLITE_OPEN_DELETEONCLOSE = 0x00000008; + + /// VFS only + static const int SQLITE_OPEN_EXCLUSIVE = 0x00000010; + + /// VFS only + static const int SQLITE_OPEN_AUTOPROXY = 0x00000020; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_URI = 0x00000040; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_MEMORY = 0x00000080; + + /// VFS only + static const int SQLITE_OPEN_MAIN_DB = 0x00000100; + + /// VFS only + static const int SQLITE_OPEN_TEMP_DB = 0x00000200; + + /// VFS only + static const int SQLITE_OPEN_TRANSIENT_DB = 0x00000400; + + /// VFS only + static const int SQLITE_OPEN_MAIN_JOURNAL = 0x00000800; + + /// VFS only + static const int SQLITE_OPEN_TEMP_JOURNAL = 0x00001000; + + /// VFS only + static const int SQLITE_OPEN_SUBJOURNAL = 0x00002000; + + /// VFS only + static const int SQLITE_OPEN_MASTER_JOURNAL = 0x00004000; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_NOMUTEX = 0x00008000; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_FULLMUTEX = 0x00010000; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_SHAREDCACHE = 0x00020000; + + /// Ok for sqlite3_open_v2() + static const int SQLITE_OPEN_PRIVATECACHE = 0x00040000; + + /// VFS only + static const int SQLITE_OPEN_WAL = 0x00080000; +} + +class Types { + static const int SQLITE_INTEGER = 1; + static const int SQLITE_FLOAT = 2; + static const int SQLITE_TEXT = 3; + static const int SQLITE_BLOB = 4; + static const int SQLITE_NULL = 5; +}
diff --git a/samples/ffi/sqlite/lib/src/bindings/signatures.dart b/samples/ffi/sqlite/lib/src/bindings/signatures.dart new file mode 100644 index 0000000..2f38dad --- /dev/null +++ b/samples/ffi/sqlite/lib/src/bindings/signatures.dart
@@ -0,0 +1,57 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:ffi"; + +import "package:ffi/ffi.dart"; + +import "types.dart"; + +typedef sqlite3_open_v2_native_t = Int32 Function(Pointer<Utf8> filename, + Pointer<Pointer<Database>> ppDb, Int32 flags, Pointer<Utf8> vfs); + +typedef sqlite3_close_v2_native_t = Int32 Function(Pointer<Database> database); + +typedef sqlite3_prepare_v2_native_t = Int32 Function( + Pointer<Database> database, + Pointer<Utf8> query, + Int32 nbytes, + Pointer<Pointer<Statement>> statementOut, + Pointer<Pointer<Utf8>> tail); + +typedef sqlite3_step_native_t = Int32 Function(Pointer<Statement> statement); + +typedef sqlite3_reset_native_t = Int32 Function(Pointer<Statement> statement); + +typedef sqlite3_finalize_native_t = Int32 Function( + Pointer<Statement> statement); + +typedef sqlite3_errstr_native_t = Pointer<Utf8> Function(Int32 error); + +typedef sqlite3_errmsg_native_t = Pointer<Utf8> Function( + Pointer<Database> database); + +typedef sqlite3_column_count_native_t = Int32 Function( + Pointer<Statement> statement); + +typedef sqlite3_column_name_native_t = Pointer<Utf8> Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_decltype_native_t = Pointer<Utf8> Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_type_native_t = Int32 Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_value_native_t = Pointer<Value> Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_double_native_t = Double Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_int_native_t = Int32 Function( + Pointer<Statement> statement, Int32 columnIndex); + +typedef sqlite3_column_text_native_t = Pointer<Utf8> Function( + Pointer<Statement> statement, Int32 columnIndex);
diff --git a/samples/ffi/sqlite/lib/src/bindings/types.dart b/samples/ffi/sqlite/lib/src/bindings/types.dart new file mode 100644 index 0000000..494cdef --- /dev/null +++ b/samples/ffi/sqlite/lib/src/bindings/types.dart
@@ -0,0 +1,75 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:ffi"; + +/// Database Connection Handle +/// +/// Each open SQLite database is represented by a pointer to an instance of +/// the opaque structure named "sqlite3". It is useful to think of an sqlite3 +/// pointer as an object. The [sqlite3_open()], [sqlite3_open16()], and +/// [sqlite3_open_v2()] interfaces are its constructors, and [sqlite3_close()] +/// is its destructor. There are many other interfaces (such as +/// [sqlite3_prepare_v2()], [sqlite3_create_function()], and +/// [sqlite3_busy_timeout()] to name but three) that are methods on an +class Database extends Struct {} + +/// SQL Statement Object +/// +/// An instance of this object represents a single SQL statement. +/// This object is variously known as a "prepared statement" or a +/// "compiled SQL statement" or simply as a "statement". +/// +/// The life of a statement object goes something like this: +/// +/// <ol> +/// <li> Create the object using [sqlite3_prepare_v2()] or a related +/// function. +/// <li> Bind values to [host parameters] using the sqlite3_bind_*() +/// interfaces. +/// <li> Run the SQL by calling [sqlite3_step()] one or more times. +/// <li> Reset the statement using [sqlite3_reset()] then go back +/// to step 2. Do this zero or more times. +/// <li> Destroy the object using [sqlite3_finalize()]. +/// </ol> +/// +/// Refer to documentation on individual methods above for additional +/// information. +class Statement extends Struct {} + +/// Dynamically Typed Value Object +/// +/// SQLite uses the sqlite3_value object to represent all values +/// that can be stored in a database table. SQLite uses dynamic typing +/// for the values it stores. ^Values stored in sqlite3_value objects +/// can be integers, floating point values, strings, BLOBs, or NULL. +/// +/// An sqlite3_value object may be either "protected" or "unprotected". +/// Some interfaces require a protected sqlite3_value. Other interfaces +/// will accept either a protected or an unprotected sqlite3_value. +/// Every interface that accepts sqlite3_value arguments specifies +/// whether or not it requires a protected sqlite3_value. +/// +/// The terms "protected" and "unprotected" refer to whether or not +/// a mutex is held. An internal mutex is held for a protected +/// sqlite3_value object but no mutex is held for an unprotected +/// sqlite3_value object. If SQLite is compiled to be single-threaded +/// (with [SQLITE_THREADSAFE=0] and with [sqlite3_threadsafe()] returning 0) +/// or if SQLite is run in one of reduced mutex modes +/// [SQLITE_CONFIG_SINGLETHREAD] or [SQLITE_CONFIG_MULTITHREAD] +/// then there is no distinction between protected and unprotected +/// sqlite3_value objects and they can be used interchangeably. However, +/// for maximum code portability it is recommended that applications +/// still make the distinction between protected and unprotected +/// sqlite3_value objects even when not strictly required. +/// +/// ^The sqlite3_value objects that are passed as parameters into the +/// implementation of [application-defined SQL functions] are protected. +/// ^The sqlite3_value object returned by +/// [sqlite3_column_value()] is unprotected. +/// Unprotected sqlite3_value objects may only be used with +/// [sqlite3_result_value()] and [sqlite3_bind_value()]. +/// The [sqlite3_value_blob | sqlite3_value_type()] family of +/// interfaces require protected sqlite3_value objects. +class Value extends Struct {}
diff --git a/samples/ffi/sqlite/lib/src/database.dart b/samples/ffi/sqlite/lib/src/database.dart index ffbe710..be2b7ef 100644 --- a/samples/ffi/sqlite/lib/src/database.dart +++ b/samples/ffi/sqlite/lib/src/database.dart
@@ -7,11 +7,13 @@ import "package:ffi/ffi.dart"; -import "third_party/sqlite/sqlite3_bindings_generated.dart" as bindings; -import "collections/closable_iterator.dart"; -import "ffi/dylib_utils.dart"; +import "bindings/bindings.dart"; -final sqlite = bindings.SQLite(dlopenPlatformSpecific("sqlite3")); +import "bindings/types.dart" as types; +import "bindings/types.dart" hide Database; + +import "bindings/constants.dart"; +import "collections/closable_iterator.dart"; /// [Database] represents an open connection to a SQLite database. /// @@ -19,27 +21,26 @@ /// /// This database interacts with SQLite synchonously. class Database { - Pointer<bindings.sqlite3> _database; + Pointer<types.Database> _database; bool _open = false; /// Open a database located at the file [path]. Database(String path, - [int flags = - bindings.SQLITE_OPEN_READWRITE | bindings.SQLITE_OPEN_CREATE]) { - Pointer<Pointer<bindings.sqlite3>> dbOut = allocate(); - final pathC = Utf8.toUtf8(path).cast<Int8>(); - final int resultCode = sqlite.sqlite3_open_v2(pathC, dbOut, flags, nullptr); + [int flags = Flags.SQLITE_OPEN_READWRITE | Flags.SQLITE_OPEN_CREATE]) { + Pointer<Pointer<types.Database>> dbOut = allocate(); + final pathC = Utf8.toUtf8(path); + final int resultCode = + bindings.sqlite3_open_v2(pathC, dbOut, flags, nullptr); _database = dbOut.value; free(dbOut); free(pathC); - if (resultCode == bindings.SQLITE_OK) { + if (resultCode == Errors.SQLITE_OK) { _open = true; } else { // Even if "open" fails, sqlite3 will still create a database object. We // can just destroy it. SQLiteException exception = _loadError(resultCode); - _open = true; close(); throw exception; } @@ -52,8 +53,8 @@ /// avoid resource leaks. void close() { assert(_open); - final int resultCode = sqlite.sqlite3_close_v2(_database); - if (resultCode == bindings.SQLITE_OK) { + final int resultCode = bindings.sqlite3_close_v2(_database); + if (resultCode == Errors.SQLITE_OK) { _open = false; } else { throw _loadError(resultCode); @@ -62,44 +63,43 @@ /// Execute a query, discarding any returned rows. void execute(String query) { - Pointer<Pointer<bindings.sqlite3_stmt>> statementOut = allocate(); - final queryC = Utf8.toUtf8(query).cast<Int8>(); - int resultCode = - sqlite.sqlite3_prepare_v2(_database, queryC, -1, statementOut, nullptr); - Pointer<bindings.sqlite3_stmt> statement = statementOut.value; + Pointer<Pointer<Statement>> statementOut = allocate(); + Pointer<Utf8> queryC = Utf8.toUtf8(query); + int resultCode = bindings.sqlite3_prepare_v2( + _database, queryC, -1, statementOut, nullptr); + Pointer<Statement> statement = statementOut.value; free(statementOut); free(queryC); - while ( - resultCode == bindings.SQLITE_ROW || resultCode == bindings.SQLITE_OK) { - resultCode = sqlite.sqlite3_step(statement); + while (resultCode == Errors.SQLITE_ROW || resultCode == Errors.SQLITE_OK) { + resultCode = bindings.sqlite3_step(statement); } - sqlite.sqlite3_finalize(statement); - if (resultCode != bindings.SQLITE_DONE) { + bindings.sqlite3_finalize(statement); + if (resultCode != Errors.SQLITE_DONE) { throw _loadError(resultCode); } } /// Evaluate a query and return the resulting rows as an iterable. Result query(String query) { - Pointer<Pointer<bindings.sqlite3_stmt>> statementOut = allocate(); - final queryC = Utf8.toUtf8(query).cast<Int8>(); - int resultCode = - sqlite.sqlite3_prepare_v2(_database, queryC, -1, statementOut, nullptr); - Pointer<bindings.sqlite3_stmt> statement = statementOut.value; + Pointer<Pointer<Statement>> statementOut = allocate(); + Pointer<Utf8> queryC = Utf8.toUtf8(query); + int resultCode = bindings.sqlite3_prepare_v2( + _database, queryC, -1, statementOut, nullptr); + Pointer<Statement> statement = statementOut.value; free(statementOut); free(queryC); - if (resultCode != bindings.SQLITE_OK) { - sqlite.sqlite3_finalize(statement); + if (resultCode != Errors.SQLITE_OK) { + bindings.sqlite3_finalize(statement); throw _loadError(resultCode); } Map<String, int> columnIndices = {}; - int columnCount = sqlite.sqlite3_column_count(statement); + int columnCount = bindings.sqlite3_column_count(statement); for (int i = 0; i < columnCount; i++) { String columnName = - sqlite.sqlite3_column_name(statement, i).cast<Utf8>().ref.toString(); + bindings.sqlite3_column_name(statement, i).ref.toString(); columnIndices[columnName] = i; } @@ -107,13 +107,12 @@ } SQLiteException _loadError([int errorCode]) { - String errorMessage = - sqlite.sqlite3_errmsg(_database).cast<Utf8>().ref.toString(); + String errorMessage = bindings.sqlite3_errmsg(_database).ref.toString(); if (errorCode == null) { return SQLiteException(errorMessage); } String errorCodeExplanation = - sqlite.sqlite3_errstr(errorCode).cast<Utf8>().ref.toString(); + bindings.sqlite3_errstr(errorCode).ref.toString(); return SQLiteException( "$errorMessage (Code $errorCode: $errorCodeExplanation)"); } @@ -127,7 +126,7 @@ class Result extends IterableBase<Row> implements ClosableIterable<Row> { final Database _database; final ClosableIterator<Row> _iterator; - final Pointer<bindings.sqlite3_stmt> _statement; + final Pointer<Statement> _statement; final Map<String, int> _columnIndices; Row _currentRow = null; @@ -144,7 +143,7 @@ } class _ResultIterator implements ClosableIterator<Row> { - final Pointer<bindings.sqlite3_stmt> _statement; + final Pointer<Statement> _statement; final Map<String, int> _columnIndices; Row _currentRow = null; @@ -157,8 +156,8 @@ throw SQLiteException("The result has already been closed."); } _currentRow?._setNotCurrent(); - int stepResult = sqlite.sqlite3_step(_statement); - if (stepResult == bindings.SQLITE_ROW) { + int stepResult = bindings.sqlite3_step(_statement); + if (stepResult == Errors.SQLITE_ROW) { _currentRow = Row._(_statement, _columnIndices); return true; } else { @@ -177,12 +176,12 @@ void close() { _currentRow?._setNotCurrent(); _closed = true; - sqlite.sqlite3_finalize(_statement); + bindings.sqlite3_finalize(_statement); } } class Row { - final Pointer<bindings.sqlite3_stmt> _statement; + final Pointer<Statement> _statement; final Map<String, int> _columnIndices; bool _isCurrentRow = true; @@ -211,11 +210,10 @@ Type dynamicType; if (convert == Convert.DynamicType) { dynamicType = - _typeFromCode(sqlite.sqlite3_column_type(_statement, columnIndex)); + _typeFromCode(bindings.sqlite3_column_type(_statement, columnIndex)); } else { - dynamicType = _typeFromText(sqlite + dynamicType = _typeFromText(bindings .sqlite3_column_decltype(_statement, columnIndex) - .cast<Utf8>() .ref .toString()); } @@ -242,7 +240,7 @@ /// integer. int readColumnByIndexAsInt(int columnIndex) { _checkIsCurrentRow(); - return sqlite.sqlite3_column_int(_statement, columnIndex); + return bindings.sqlite3_column_int(_statement, columnIndex); } /// Reads column [columnName] and converts to [Type.Text] if not text. @@ -253,11 +251,7 @@ /// Reads column [columnIndex] and converts to [Type.Text] if not text. String readColumnByIndexAsText(int columnIndex) { _checkIsCurrentRow(); - return sqlite - .sqlite3_column_text(_statement, columnIndex) - .cast<Utf8>() - .ref - .toString(); + return bindings.sqlite3_column_text(_statement, columnIndex).ref.toString(); } void _checkIsCurrentRow() { @@ -275,15 +269,15 @@ Type _typeFromCode(int code) { switch (code) { - case bindings.SQLITE_INTEGER: + case Types.SQLITE_INTEGER: return Type.Integer; - case bindings.SQLITE_FLOAT: + case Types.SQLITE_FLOAT: return Type.Float; - case bindings.SQLITE_TEXT: + case Types.SQLITE_TEXT: return Type.Text; - case bindings.SQLITE_BLOB: + case Types.SQLITE_BLOB: return Type.Blob; - case bindings.SQLITE_NULL: + case Types.SQLITE_NULL: return Type.Null; } throw Exception("Unknown type [$code]");
diff --git a/samples/ffi/sqlite/lib/src/third_party/sqlite/sqlite3_bindings_generated.dart b/samples/ffi/sqlite/lib/src/third_party/sqlite/sqlite3_bindings_generated.dart deleted file mode 100644 index bfbd4c8..0000000 --- a/samples/ffi/sqlite/lib/src/third_party/sqlite/sqlite3_bindings_generated.dart +++ /dev/null
@@ -1,1968 +0,0 @@ -// 2001 September 15 -// -// The author disclaims copyright to this source code. In place of -// a legal notice, here is a blessing: -// -// May you do good and not evil. -// May you find forgiveness for yourself and forgive others. -// May you share freely, never taking more than you give. - -import 'dart:ffi' as ffi; - -/// SQLite bindings. -class SQLite { - /// Holds the Dynamic library. - final ffi.DynamicLibrary _dylib; - - /// The symbols are looked up in [dynamicLibrary]. - SQLite(ffi.DynamicLibrary dynamicLibrary) : _dylib = dynamicLibrary; - - int sqlite3_close_v2( - ffi.Pointer<sqlite3> arg0, - ) { - _sqlite3_close_v2 ??= - _dylib.lookupFunction<_c_sqlite3_close_v2, _dart_sqlite3_close_v2>( - 'sqlite3_close_v2'); - return _sqlite3_close_v2( - arg0, - ); - } - - _dart_sqlite3_close_v2 _sqlite3_close_v2; - - int sqlite3_open_v2( - ffi.Pointer<ffi.Int8> filename, - ffi.Pointer<ffi.Pointer<sqlite3>> ppDb, - int flags, - ffi.Pointer<ffi.Int8> zVfs, - ) { - _sqlite3_open_v2 ??= - _dylib.lookupFunction<_c_sqlite3_open_v2, _dart_sqlite3_open_v2>( - 'sqlite3_open_v2'); - return _sqlite3_open_v2( - filename, - ppDb, - flags, - zVfs, - ); - } - - _dart_sqlite3_open_v2 _sqlite3_open_v2; - - ffi.Pointer<ffi.Int8> sqlite3_errmsg( - ffi.Pointer<sqlite3> arg0, - ) { - _sqlite3_errmsg ??= - _dylib.lookupFunction<_c_sqlite3_errmsg, _dart_sqlite3_errmsg>( - 'sqlite3_errmsg'); - return _sqlite3_errmsg( - arg0, - ); - } - - _dart_sqlite3_errmsg _sqlite3_errmsg; - - ffi.Pointer<ffi.Int8> sqlite3_errstr( - int arg0, - ) { - _sqlite3_errstr ??= - _dylib.lookupFunction<_c_sqlite3_errstr, _dart_sqlite3_errstr>( - 'sqlite3_errstr'); - return _sqlite3_errstr( - arg0, - ); - } - - _dart_sqlite3_errstr _sqlite3_errstr; - - int sqlite3_prepare_v2( - ffi.Pointer<sqlite3> db, - ffi.Pointer<ffi.Int8> zSql, - int nByte, - ffi.Pointer<ffi.Pointer<sqlite3_stmt>> ppStmt, - ffi.Pointer<ffi.Pointer<ffi.Int8>> pzTail, - ) { - _sqlite3_prepare_v2 ??= - _dylib.lookupFunction<_c_sqlite3_prepare_v2, _dart_sqlite3_prepare_v2>( - 'sqlite3_prepare_v2'); - return _sqlite3_prepare_v2( - db, - zSql, - nByte, - ppStmt, - pzTail, - ); - } - - _dart_sqlite3_prepare_v2 _sqlite3_prepare_v2; - - /// CAPI3REF: Number Of Columns In A Result Set - /// METHOD: sqlite3_stmt - /// - /// ^Return the number of columns in the result set returned by the - /// [prepared statement]. ^If this routine returns 0, that means the - /// [prepared statement] returns no data (for example an [UPDATE]). - /// ^However, just because this routine returns a positive number does not - /// mean that one or more rows of data will be returned. ^A SELECT statement - /// will always have a positive sqlite3_column_count() but depending on the - /// WHERE clause constraints and the table content, it might return no rows. - /// - /// See also: [sqlite3_data_count()] - int sqlite3_column_count( - ffi.Pointer<sqlite3_stmt> pStmt, - ) { - _sqlite3_column_count ??= _dylib.lookupFunction<_c_sqlite3_column_count, - _dart_sqlite3_column_count>('sqlite3_column_count'); - return _sqlite3_column_count( - pStmt, - ); - } - - _dart_sqlite3_column_count _sqlite3_column_count; - - /// CAPI3REF: Column Names In A Result Set - /// METHOD: sqlite3_stmt - /// - /// ^These routines return the name assigned to a particular column - /// in the result set of a [SELECT] statement. ^The sqlite3_column_name() - /// interface returns a pointer to a zero-terminated UTF-8 string - /// and sqlite3_column_name16() returns a pointer to a zero-terminated - /// UTF-16 string. ^The first parameter is the [prepared statement] - /// that implements the [SELECT] statement. ^The second parameter is the - /// column number. ^The leftmost column is number 0. - /// - /// ^The returned string pointer is valid until either the [prepared statement] - /// is destroyed by [sqlite3_finalize()] or until the statement is automatically - /// reprepared by the first call to [sqlite3_step()] for a particular run - /// or until the next call to - /// sqlite3_column_name() or sqlite3_column_name16() on the same column. - /// - /// ^If sqlite3_malloc() fails during the processing of either routine - /// (for example during a conversion from UTF-8 to UTF-16) then a - /// NULL pointer is returned. - /// - /// ^The name of a result column is the value of the "AS" clause for - /// that column, if there is an AS clause. If there is no AS clause - /// then the name of the column is unspecified and may change from - /// one release of SQLite to the next. - ffi.Pointer<ffi.Int8> sqlite3_column_name( - ffi.Pointer<sqlite3_stmt> arg0, - int N, - ) { - _sqlite3_column_name ??= _dylib.lookupFunction<_c_sqlite3_column_name, - _dart_sqlite3_column_name>('sqlite3_column_name'); - return _sqlite3_column_name( - arg0, - N, - ); - } - - _dart_sqlite3_column_name _sqlite3_column_name; - - /// CAPI3REF: Declared Datatype Of A Query Result - /// METHOD: sqlite3_stmt - /// - /// ^(The first parameter is a [prepared statement]. - /// If this statement is a [SELECT] statement and the Nth column of the - /// returned result set of that [SELECT] is a table column (not an - /// expression or subquery) then the declared type of the table - /// column is returned.)^ ^If the Nth column of the result set is an - /// expression or subquery, then a NULL pointer is returned. - /// ^The returned string is always UTF-8 encoded. - /// - /// ^(For example, given the database schema: - /// - /// CREATE TABLE t1(c1 VARIANT); - /// - /// and the following statement to be compiled: - /// - /// SELECT c1 + 1, c1 FROM t1; - /// - /// this routine would return the string "VARIANT" for the second result - /// column (i==1), and a NULL pointer for the first result column (i==0).)^ - /// - /// ^SQLite uses dynamic run-time typing. ^So just because a column - /// is declared to contain a particular type does not mean that the - /// data stored in that column is of the declared type. SQLite is - /// strongly typed, but the typing is dynamic not static. ^Type - /// is associated with individual values, not with the containers - /// used to hold those values. - ffi.Pointer<ffi.Int8> sqlite3_column_decltype( - ffi.Pointer<sqlite3_stmt> arg0, - int arg1, - ) { - _sqlite3_column_decltype ??= _dylib.lookupFunction< - _c_sqlite3_column_decltype, - _dart_sqlite3_column_decltype>('sqlite3_column_decltype'); - return _sqlite3_column_decltype( - arg0, - arg1, - ); - } - - _dart_sqlite3_column_decltype _sqlite3_column_decltype; - - /// CAPI3REF: Evaluate An SQL Statement - /// METHOD: sqlite3_stmt - /// - /// After a [prepared statement] has been prepared using any of - /// [sqlite3_prepare_v2()], [sqlite3_prepare_v3()], [sqlite3_prepare16_v2()], - /// or [sqlite3_prepare16_v3()] or one of the legacy - /// interfaces [sqlite3_prepare()] or [sqlite3_prepare16()], this function - /// must be called one or more times to evaluate the statement. - /// - /// The details of the behavior of the sqlite3_step() interface depend - /// on whether the statement was prepared using the newer "vX" interfaces - /// [sqlite3_prepare_v3()], [sqlite3_prepare_v2()], [sqlite3_prepare16_v3()], - /// [sqlite3_prepare16_v2()] or the older legacy - /// interfaces [sqlite3_prepare()] and [sqlite3_prepare16()]. The use of the - /// new "vX" interface is recommended for new applications but the legacy - /// interface will continue to be supported. - /// - /// ^In the legacy interface, the return value will be either [SQLITE_BUSY], - /// [SQLITE_DONE], [SQLITE_ROW], [SQLITE_ERROR], or [SQLITE_MISUSE]. - /// ^With the "v2" interface, any of the other [result codes] or - /// [extended result codes] might be returned as well. - /// - /// ^[SQLITE_BUSY] means that the database engine was unable to acquire the - /// database locks it needs to do its job. ^If the statement is a [COMMIT] - /// or occurs outside of an explicit transaction, then you can retry the - /// statement. If the statement is not a [COMMIT] and occurs within an - /// explicit transaction then you should rollback the transaction before - /// continuing. - /// - /// ^[SQLITE_DONE] means that the statement has finished executing - /// successfully. sqlite3_step() should not be called again on this virtual - /// machine without first calling [sqlite3_reset()] to reset the virtual - /// machine back to its initial state. - /// - /// ^If the SQL statement being executed returns any data, then [SQLITE_ROW] - /// is returned each time a new row of data is ready for processing by the - /// caller. The values may be accessed using the [column access functions]. - /// sqlite3_step() is called again to retrieve the next row of data. - /// - /// ^[SQLITE_ERROR] means that a run-time error (such as a constraint - /// violation) has occurred. sqlite3_step() should not be called again on - /// the VM. More information may be found by calling [sqlite3_errmsg()]. - /// ^With the legacy interface, a more specific error code (for example, - /// [SQLITE_INTERRUPT], [SQLITE_SCHEMA], [SQLITE_CORRUPT], and so forth) - /// can be obtained by calling [sqlite3_reset()] on the - /// [prepared statement]. ^In the "v2" interface, - /// the more specific error code is returned directly by sqlite3_step(). - /// - /// [SQLITE_MISUSE] means that the this routine was called inappropriately. - /// Perhaps it was called on a [prepared statement] that has - /// already been [sqlite3_finalize | finalized] or on one that had - /// previously returned [SQLITE_ERROR] or [SQLITE_DONE]. Or it could - /// be the case that the same database connection is being used by two or - /// more threads at the same moment in time. - /// - /// For all versions of SQLite up to and including 3.6.23.1, a call to - /// [sqlite3_reset()] was required after sqlite3_step() returned anything - /// other than [SQLITE_ROW] before any subsequent invocation of - /// sqlite3_step(). Failure to reset the prepared statement using - /// [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from - /// sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1], - /// sqlite3_step() began - /// calling [sqlite3_reset()] automatically in this circumstance rather - /// than returning [SQLITE_MISUSE]. This is not considered a compatibility - /// break because any application that ever receives an SQLITE_MISUSE error - /// is broken by definition. The [SQLITE_OMIT_AUTORESET] compile-time option - /// can be used to restore the legacy behavior. - /// - /// <b>Goofy Interface Alert:</b> In the legacy interface, the sqlite3_step() - /// API always returns a generic error code, [SQLITE_ERROR], following any - /// error other than [SQLITE_BUSY] and [SQLITE_MISUSE]. You must call - /// [sqlite3_reset()] or [sqlite3_finalize()] in order to find one of the - /// specific [error codes] that better describes the error. - /// We admit that this is a goofy design. The problem has been fixed - /// with the "v2" interface. If you prepare all of your SQL statements - /// using [sqlite3_prepare_v3()] or [sqlite3_prepare_v2()] - /// or [sqlite3_prepare16_v2()] or [sqlite3_prepare16_v3()] instead - /// of the legacy [sqlite3_prepare()] and [sqlite3_prepare16()] interfaces, - /// then the more specific [error codes] are returned directly - /// by sqlite3_step(). The use of the "vX" interfaces is recommended. - int sqlite3_step( - ffi.Pointer<sqlite3_stmt> arg0, - ) { - _sqlite3_step ??= _dylib - .lookupFunction<_c_sqlite3_step, _dart_sqlite3_step>('sqlite3_step'); - return _sqlite3_step( - arg0, - ); - } - - _dart_sqlite3_step _sqlite3_step; - - int sqlite3_column_int( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, - ) { - _sqlite3_column_int ??= - _dylib.lookupFunction<_c_sqlite3_column_int, _dart_sqlite3_column_int>( - 'sqlite3_column_int'); - return _sqlite3_column_int( - arg0, - iCol, - ); - } - - _dart_sqlite3_column_int _sqlite3_column_int; - - ffi.Pointer<ffi.Uint8> sqlite3_column_text( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, - ) { - _sqlite3_column_text ??= _dylib.lookupFunction<_c_sqlite3_column_text, - _dart_sqlite3_column_text>('sqlite3_column_text'); - return _sqlite3_column_text( - arg0, - iCol, - ); - } - - _dart_sqlite3_column_text _sqlite3_column_text; - - int sqlite3_column_type( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, - ) { - _sqlite3_column_type ??= _dylib.lookupFunction<_c_sqlite3_column_type, - _dart_sqlite3_column_type>('sqlite3_column_type'); - return _sqlite3_column_type( - arg0, - iCol, - ); - } - - _dart_sqlite3_column_type _sqlite3_column_type; - - /// CAPI3REF: Destroy A Prepared Statement Object - /// DESTRUCTOR: sqlite3_stmt - /// - /// ^The sqlite3_finalize() function is called to delete a [prepared statement]. - /// ^If the most recent evaluation of the statement encountered no errors - /// or if the statement is never been evaluated, then sqlite3_finalize() returns - /// SQLITE_OK. ^If the most recent evaluation of statement S failed, then - /// sqlite3_finalize(S) returns the appropriate [error code] or - /// [extended error code]. - /// - /// ^The sqlite3_finalize(S) routine can be called at any point during - /// the life cycle of [prepared statement] S: - /// before statement S is ever evaluated, after - /// one or more calls to [sqlite3_reset()], or after any call - /// to [sqlite3_step()] regardless of whether or not the statement has - /// completed execution. - /// - /// ^Invoking sqlite3_finalize() on a NULL pointer is a harmless no-op. - /// - /// The application must finalize every [prepared statement] in order to avoid - /// resource leaks. It is a grievous error for the application to try to use - /// a prepared statement after it has been finalized. Any use of a prepared - /// statement after it has been finalized can result in undefined and - /// undesirable behavior such as segfaults and heap corruption. - int sqlite3_finalize( - ffi.Pointer<sqlite3_stmt> pStmt, - ) { - _sqlite3_finalize ??= - _dylib.lookupFunction<_c_sqlite3_finalize, _dart_sqlite3_finalize>( - 'sqlite3_finalize'); - return _sqlite3_finalize( - pStmt, - ); - } - - _dart_sqlite3_finalize _sqlite3_finalize; -} - -class sqlite3 extends ffi.Struct {} - -class sqlite3_file extends ffi.Struct {} - -class sqlite3_io_methods extends ffi.Struct { - @ffi.Int32() - int iVersion; - - ffi.Pointer<ffi.NativeFunction<_typedefC_1>> xClose; - - ffi.Pointer<ffi.NativeFunction<_typedefC_2>> xRead; - - ffi.Pointer<ffi.NativeFunction<_typedefC_3>> xWrite; - - ffi.Pointer<ffi.NativeFunction<_typedefC_4>> xTruncate; - - ffi.Pointer<ffi.NativeFunction<_typedefC_5>> xSync; - - ffi.Pointer<ffi.NativeFunction<_typedefC_6>> xFileSize; - - ffi.Pointer<ffi.NativeFunction<_typedefC_7>> xLock; - - ffi.Pointer<ffi.NativeFunction<_typedefC_8>> xUnlock; - - ffi.Pointer<ffi.NativeFunction<_typedefC_9>> xCheckReservedLock; - - ffi.Pointer<ffi.NativeFunction<_typedefC_10>> xFileControl; - - ffi.Pointer<ffi.NativeFunction<_typedefC_11>> xSectorSize; - - ffi.Pointer<ffi.NativeFunction<_typedefC_12>> xDeviceCharacteristics; - - /// Methods above are valid for version 1 - ffi.Pointer<ffi.NativeFunction<_typedefC_13>> xShmMap; - - ffi.Pointer<ffi.NativeFunction<_typedefC_14>> xShmLock; - - ffi.Pointer<ffi.NativeFunction<_typedefC_15>> xShmBarrier; - - ffi.Pointer<ffi.NativeFunction<_typedefC_16>> xShmUnmap; - - /// Methods above are valid for version 2 - ffi.Pointer<ffi.NativeFunction<_typedefC_17>> xFetch; - - ffi.Pointer<ffi.NativeFunction<_typedefC_18>> xUnfetch; -} - -class sqlite3_mutex extends ffi.Struct {} - -class sqlite3_api_routines extends ffi.Struct {} - -class sqlite3_vfs extends ffi.Struct {} - -class sqlite3_mem_methods extends ffi.Struct {} - -class sqlite3_stmt extends ffi.Struct {} - -class sqlite3_value extends ffi.Struct {} - -class sqlite3_context extends ffi.Struct {} - -/// CAPI3REF: Virtual Table Instance Object -/// KEYWORDS: sqlite3_vtab -/// -/// Every [virtual table module] implementation uses a subclass -/// of this object to describe a particular instance -/// of the [virtual table]. Each subclass will -/// be tailored to the specific needs of the module implementation. -/// The purpose of this superclass is to define certain fields that are -/// common to all module implementations. -/// -/// ^Virtual tables methods can set an error message by assigning a -/// string obtained from [sqlite3_mprintf()] to zErrMsg. The method should -/// take care that any prior string is freed by a call to [sqlite3_free()] -/// prior to assigning a new string to zErrMsg. ^After the error message -/// is delivered up to the client application, the string will be automatically -/// freed by sqlite3_free() and the zErrMsg field will be zeroed. -class sqlite3_vtab extends ffi.Struct {} - -/// CAPI3REF: Virtual Table Indexing Information -/// KEYWORDS: sqlite3_index_info -/// -/// The sqlite3_index_info structure and its substructures is used as part -/// of the [virtual table] interface to -/// pass information into and receive the reply from the [xBestIndex] -/// method of a [virtual table module]. The fields under **Inputs** are the -/// inputs to xBestIndex and are read-only. xBestIndex inserts its -/// results into the **Outputs** fields. -/// -/// ^(The aConstraint[] array records WHERE clause constraints of the form: -/// -/// <blockquote>column OP expr</blockquote> -/// -/// where OP is =, <, <=, >, or >=.)^ ^(The particular operator is -/// stored in aConstraint[].op using one of the -/// [SQLITE_INDEX_CONSTRAINT_EQ | SQLITE_INDEX_CONSTRAINT_ values].)^ -/// ^(The index of the column is stored in -/// aConstraint[].iColumn.)^ ^(aConstraint[].usable is TRUE if the -/// expr on the right-hand side can be evaluated (and thus the constraint -/// is usable) and false if it cannot.)^ -/// -/// ^The optimizer automatically inverts terms of the form "expr OP column" -/// and makes other simplifications to the WHERE clause in an attempt to -/// get as many WHERE clause terms into the form shown above as possible. -/// ^The aConstraint[] array only reports WHERE clause terms that are -/// relevant to the particular virtual table being queried. -/// -/// ^Information about the ORDER BY clause is stored in aOrderBy[]. -/// ^Each term of aOrderBy records a column of the ORDER BY clause. -/// -/// The colUsed field indicates which columns of the virtual table may be -/// required by the current scan. Virtual table columns are numbered from -/// zero in the order in which they appear within the CREATE TABLE statement -/// passed to sqlite3_declare_vtab(). For the first 63 columns (columns 0-62), -/// the corresponding bit is set within the colUsed mask if the column may be -/// required by SQLite. If the table has at least 64 columns and any column -/// to the right of the first 63 is required, then bit 63 of colUsed is also -/// set. In other words, column iCol may be required if the expression -/// (colUsed & ((sqlite3_uint64)1 << (iCol>=63 ? 63 : iCol))) evaluates to -/// non-zero. -/// -/// The [xBestIndex] method must fill aConstraintUsage[] with information -/// about what parameters to pass to xFilter. ^If argvIndex>0 then -/// the right-hand side of the corresponding aConstraint[] is evaluated -/// and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit -/// is true, then the constraint is assumed to be fully handled by the -/// virtual table and might not be checked again by the byte code.)^ ^(The -/// aConstraintUsage[].omit flag is an optimization hint. When the omit flag -/// is left in its default setting of false, the constraint will always be -/// checked separately in byte code. If the omit flag is change to true, then -/// the constraint may or may not be checked in byte code. In other words, -/// when the omit flag is true there is no guarantee that the constraint will -/// not be checked again using byte code.)^ -/// -/// ^The idxNum and idxPtr values are recorded and passed into the -/// [xFilter] method. -/// ^[sqlite3_free()] is used to free idxPtr if and only if -/// needToFreeIdxPtr is true. -/// -/// ^The orderByConsumed means that output from [xFilter]/[xNext] will occur in -/// the correct order to satisfy the ORDER BY clause so that no separate -/// sorting step is required. -/// -/// ^The estimatedCost value is an estimate of the cost of a particular -/// strategy. A cost of N indicates that the cost of the strategy is similar -/// to a linear scan of an SQLite table with N rows. A cost of log(N) -/// indicates that the expense of the operation is similar to that of a -/// binary search on a unique indexed field of an SQLite table with N rows. -/// -/// ^The estimatedRows value is an estimate of the number of rows that -/// will be returned by the strategy. -/// -/// The xBestIndex method may optionally populate the idxFlags field with a -/// mask of SQLITE_INDEX_SCAN_* flags. Currently there is only one such flag - -/// SQLITE_INDEX_SCAN_UNIQUE. If the xBestIndex method sets this flag, SQLite -/// assumes that the strategy may visit at most one row. -/// -/// Additionally, if xBestIndex sets the SQLITE_INDEX_SCAN_UNIQUE flag, then -/// SQLite also assumes that if a call to the xUpdate() method is made as -/// part of the same statement to delete or update a virtual table row and the -/// implementation returns SQLITE_CONSTRAINT, then there is no need to rollback -/// any database changes. In other words, if the xUpdate() returns -/// SQLITE_CONSTRAINT, the database contents must be exactly as they were -/// before xUpdate was called. By contrast, if SQLITE_INDEX_SCAN_UNIQUE is not -/// set and xUpdate returns SQLITE_CONSTRAINT, any database changes made by -/// the xUpdate method are automatically rolled back by SQLite. -/// -/// IMPORTANT: The estimatedRows field was added to the sqlite3_index_info -/// structure for SQLite [version 3.8.2] ([dateof:3.8.2]). -/// If a virtual table extension is -/// used with an SQLite version earlier than 3.8.2, the results of attempting -/// to read or write the estimatedRows field are undefined (but are likely -/// to include crashing the application). The estimatedRows field should -/// therefore only be used if [sqlite3_libversion_number()] returns a -/// value greater than or equal to 3008002. Similarly, the idxFlags field -/// was added for [version 3.9.0] ([dateof:3.9.0]). -/// It may therefore only be used if -/// sqlite3_libversion_number() returns a value greater than or equal to -/// 3009000. -class sqlite3_index_info extends ffi.Struct {} - -/// CAPI3REF: Virtual Table Cursor Object -/// KEYWORDS: sqlite3_vtab_cursor {virtual table cursor} -/// -/// Every [virtual table module] implementation uses a subclass of the -/// following structure to describe cursors that point into the -/// [virtual table] and are used -/// to loop through the virtual table. Cursors are created using the -/// [sqlite3_module.xOpen | xOpen] method of the module and are destroyed -/// by the [sqlite3_module.xClose | xClose] method. Cursors are used -/// by the [xFilter], [xNext], [xEof], [xColumn], and [xRowid] methods -/// of the module. Each module implementation will define -/// the content of a cursor structure to suit its own needs. -/// -/// This superclass exists in order to define fields of the cursor that -/// are common to all implementations. -class sqlite3_vtab_cursor extends ffi.Struct {} - -/// CAPI3REF: Virtual Table Object -/// KEYWORDS: sqlite3_module {virtual table module} -/// -/// This structure, sometimes called a "virtual table module", -/// defines the implementation of a [virtual table]. -/// This structure consists mostly of methods for the module. -/// -/// ^A virtual table module is created by filling in a persistent -/// instance of this structure and passing a pointer to that instance -/// to [sqlite3_create_module()] or [sqlite3_create_module_v2()]. -/// ^The registration remains valid until it is replaced by a different -/// module or until the [database connection] closes. The content -/// of this structure must not change while it is registered with -/// any database connection. -class sqlite3_module extends ffi.Struct {} - -class sqlite3_blob extends ffi.Struct {} - -class sqlite3_mutex_methods extends ffi.Struct {} - -class sqlite3_str extends ffi.Struct {} - -class sqlite3_pcache extends ffi.Struct {} - -class sqlite3_pcache_page extends ffi.Struct {} - -class sqlite3_pcache_methods2 extends ffi.Struct {} - -class sqlite3_pcache_methods extends ffi.Struct {} - -class sqlite3_backup extends ffi.Struct {} - -/// CAPI3REF: Database Snapshot -/// KEYWORDS: {snapshot} {sqlite3_snapshot} -/// -/// An instance of the snapshot object records the state of a [WAL mode] -/// database for some specific point in history. -/// -/// In [WAL mode], multiple [database connections] that are open on the -/// same database file can each be reading a different historical version -/// of the database file. When a [database connection] begins a read -/// transaction, that connection sees an unchanging copy of the database -/// as it existed for the point in time when the transaction first started. -/// Subsequent changes to the database from other connections are not seen -/// by the reader until a new read transaction is started. -/// -/// The sqlite3_snapshot object records state information about an historical -/// version of the database file so that it is possible to later open a new read -/// transaction that sees that historical version of the database rather than -/// the most recent version. -class sqlite3_snapshot extends ffi.Struct {} - -/// A pointer to a structure of the following type is passed as the first -/// argument to callbacks registered using rtree_geometry_callback(). -class sqlite3_rtree_geometry extends ffi.Struct {} - -/// A pointer to a structure of the following type is passed as the -/// argument to scored geometry callback registered using -/// sqlite3_rtree_query_callback(). -/// -/// Note that the first 5 fields of this structure are identical to -/// sqlite3_rtree_geometry. This structure is a subclass of -/// sqlite3_rtree_geometry. -class sqlite3_rtree_query_info extends ffi.Struct {} - -/// EXTENSION API FUNCTIONS -/// -/// xUserData(pFts): -/// Return a copy of the context pointer the extension function was -/// registered with. -/// -/// xColumnTotalSize(pFts, iCol, pnToken): -/// If parameter iCol is less than zero, set output variable *pnToken -/// to the total number of tokens in the FTS5 table. Or, if iCol is -/// non-negative but less than the number of columns in the table, return -/// the total number of tokens in column iCol, considering all rows in -/// the FTS5 table. -/// -/// If parameter iCol is greater than or equal to the number of columns -/// in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -/// an OOM condition or IO error), an appropriate SQLite error code is -/// returned. -/// -/// xColumnCount(pFts): -/// Return the number of columns in the table. -/// -/// xColumnSize(pFts, iCol, pnToken): -/// If parameter iCol is less than zero, set output variable *pnToken -/// to the total number of tokens in the current row. Or, if iCol is -/// non-negative but less than the number of columns in the table, set -/// *pnToken to the number of tokens in column iCol of the current row. -/// -/// If parameter iCol is greater than or equal to the number of columns -/// in the table, SQLITE_RANGE is returned. Or, if an error occurs (e.g. -/// an OOM condition or IO error), an appropriate SQLite error code is -/// returned. -/// -/// This function may be quite inefficient if used with an FTS5 table -/// created with the "columnsize=0" option. -/// -/// xColumnText: -/// This function attempts to retrieve the text of column iCol of the -/// current document. If successful, (*pz) is set to point to a buffer -/// containing the text in utf-8 encoding, (*pn) is set to the size in bytes -/// (not characters) of the buffer and SQLITE_OK is returned. Otherwise, -/// if an error occurs, an SQLite error code is returned and the final values -/// of (*pz) and (*pn) are undefined. -/// -/// xPhraseCount: -/// Returns the number of phrases in the current query expression. -/// -/// xPhraseSize: -/// Returns the number of tokens in phrase iPhrase of the query. Phrases -/// are numbered starting from zero. -/// -/// xInstCount: -/// Set *pnInst to the total number of occurrences of all phrases within -/// the query within the current row. Return SQLITE_OK if successful, or -/// an error code (i.e. SQLITE_NOMEM) if an error occurs. -/// -/// This API can be quite slow if used with an FTS5 table created with the -/// "detail=none" or "detail=column" option. If the FTS5 table is created -/// with either "detail=none" or "detail=column" and "content=" option -/// (i.e. if it is a contentless table), then this API always returns 0. -/// -/// xInst: -/// Query for the details of phrase match iIdx within the current row. -/// Phrase matches are numbered starting from zero, so the iIdx argument -/// should be greater than or equal to zero and smaller than the value -/// output by xInstCount(). -/// -/// Usually, output parameter *piPhrase is set to the phrase number, *piCol -/// to the column in which it occurs and *piOff the token offset of the -/// first token of the phrase. Returns SQLITE_OK if successful, or an error -/// code (i.e. SQLITE_NOMEM) if an error occurs. -/// -/// This API can be quite slow if used with an FTS5 table created with the -/// "detail=none" or "detail=column" option. -/// -/// xRowid: -/// Returns the rowid of the current row. -/// -/// xTokenize: -/// Tokenize text using the tokenizer belonging to the FTS5 table. -/// -/// xQueryPhrase(pFts5, iPhrase, pUserData, xCallback): -/// This API function is used to query the FTS table for phrase iPhrase -/// of the current query. Specifically, a query equivalent to: -/// -/// ... FROM ftstable WHERE ftstable MATCH $p ORDER BY rowid -/// -/// with $p set to a phrase equivalent to the phrase iPhrase of the -/// current query is executed. Any column filter that applies to -/// phrase iPhrase of the current query is included in $p. For each -/// row visited, the callback function passed as the fourth argument -/// is invoked. The context and API objects passed to the callback -/// function may be used to access the properties of each matched row. -/// Invoking Api.xUserData() returns a copy of the pointer passed as -/// the third argument to pUserData. -/// -/// If the callback function returns any value other than SQLITE_OK, the -/// query is abandoned and the xQueryPhrase function returns immediately. -/// If the returned value is SQLITE_DONE, xQueryPhrase returns SQLITE_OK. -/// Otherwise, the error code is propagated upwards. -/// -/// If the query runs to completion without incident, SQLITE_OK is returned. -/// Or, if some error occurs before the query completes or is aborted by -/// the callback, an SQLite error code is returned. -/// -/// -/// xSetAuxdata(pFts5, pAux, xDelete) -/// -/// Save the pointer passed as the second argument as the extension function's -/// "auxiliary data". The pointer may then be retrieved by the current or any -/// future invocation of the same fts5 extension function made as part of -/// the same MATCH query using the xGetAuxdata() API. -/// -/// Each extension function is allocated a single auxiliary data slot for -/// each FTS query (MATCH expression). If the extension function is invoked -/// more than once for a single FTS query, then all invocations share a -/// single auxiliary data context. -/// -/// If there is already an auxiliary data pointer when this function is -/// invoked, then it is replaced by the new pointer. If an xDelete callback -/// was specified along with the original pointer, it is invoked at this -/// point. -/// -/// The xDelete callback, if one is specified, is also invoked on the -/// auxiliary data pointer after the FTS5 query has finished. -/// -/// If an error (e.g. an OOM condition) occurs within this function, -/// the auxiliary data is set to NULL and an error code returned. If the -/// xDelete parameter was not NULL, it is invoked on the auxiliary data -/// pointer before returning. -/// -/// -/// xGetAuxdata(pFts5, bClear) -/// -/// Returns the current auxiliary data pointer for the fts5 extension -/// function. See the xSetAuxdata() method for details. -/// -/// If the bClear argument is non-zero, then the auxiliary data is cleared -/// (set to NULL) before this function returns. In this case the xDelete, -/// if any, is not invoked. -/// -/// -/// xRowCount(pFts5, pnRow) -/// -/// This function is used to retrieve the total number of rows in the table. -/// In other words, the same value that would be returned by: -/// -/// SELECT count(*) FROM ftstable; -/// -/// xPhraseFirst() -/// This function is used, along with type Fts5PhraseIter and the xPhraseNext -/// method, to iterate through all instances of a single query phrase within -/// the current row. This is the same information as is accessible via the -/// xInstCount/xInst APIs. While the xInstCount/xInst APIs are more convenient -/// to use, this API may be faster under some circumstances. To iterate -/// through instances of phrase iPhrase, use the following code: -/// -/// Fts5PhraseIter iter; -/// int iCol, iOff; -/// for(pApi->xPhraseFirst(pFts, iPhrase, &iter, &iCol, &iOff); -/// iCol>=0; -/// pApi->xPhraseNext(pFts, &iter, &iCol, &iOff) -/// ){ -/// // An instance of phrase iPhrase at offset iOff of column iCol -/// } -/// -/// The Fts5PhraseIter structure is defined above. Applications should not -/// modify this structure directly - it should only be used as shown above -/// with the xPhraseFirst() and xPhraseNext() API methods (and by -/// xPhraseFirstColumn() and xPhraseNextColumn() as illustrated below). -/// -/// This API can be quite slow if used with an FTS5 table created with the -/// "detail=none" or "detail=column" option. If the FTS5 table is created -/// with either "detail=none" or "detail=column" and "content=" option -/// (i.e. if it is a contentless table), then this API always iterates -/// through an empty set (all calls to xPhraseFirst() set iCol to -1). -/// -/// xPhraseNext() -/// See xPhraseFirst above. -/// -/// xPhraseFirstColumn() -/// This function and xPhraseNextColumn() are similar to the xPhraseFirst() -/// and xPhraseNext() APIs described above. The difference is that instead -/// of iterating through all instances of a phrase in the current row, these -/// APIs are used to iterate through the set of columns in the current row -/// that contain one or more instances of a specified phrase. For example: -/// -/// Fts5PhraseIter iter; -/// int iCol; -/// for(pApi->xPhraseFirstColumn(pFts, iPhrase, &iter, &iCol); -/// iCol>=0; -/// pApi->xPhraseNextColumn(pFts, &iter, &iCol) -/// ){ -/// // Column iCol contains at least one instance of phrase iPhrase -/// } -/// -/// This API can be quite slow if used with an FTS5 table created with the -/// "detail=none" option. If the FTS5 table is created with either -/// "detail=none" "content=" option (i.e. if it is a contentless table), -/// then this API always iterates through an empty set (all calls to -/// xPhraseFirstColumn() set iCol to -1). -/// -/// The information accessed using this API and its companion -/// xPhraseFirstColumn() may also be obtained using xPhraseFirst/xPhraseNext -/// (or xInst/xInstCount). The chief advantage of this API is that it is -/// significantly more efficient than those alternatives when used with -/// "detail=column" tables. -/// -/// xPhraseNextColumn() -/// See xPhraseFirstColumn above. -class Fts5ExtensionApi extends ffi.Struct {} - -class Fts5Context extends ffi.Struct {} - -class Fts5PhraseIter extends ffi.Struct {} - -class Fts5Tokenizer extends ffi.Struct {} - -class fts5_tokenizer extends ffi.Struct {} - -class fts5_api extends ffi.Struct {} - -const String SQLITE_VERSION = '3.32.3'; - -const int SQLITE_VERSION_NUMBER = 3032003; - -const String SQLITE_SOURCE_ID = - '2020-06-18 14:00:33 7ebdfa80be8e8e73324b8d66b3460222eb74c7e9dfd655b48d6ca7e1933cc8fd'; - -const int SQLITE_OK = 0; - -const int SQLITE_ERROR = 1; - -const int SQLITE_INTERNAL = 2; - -const int SQLITE_PERM = 3; - -const int SQLITE_ABORT = 4; - -const int SQLITE_BUSY = 5; - -const int SQLITE_LOCKED = 6; - -const int SQLITE_NOMEM = 7; - -const int SQLITE_READONLY = 8; - -const int SQLITE_INTERRUPT = 9; - -const int SQLITE_IOERR = 10; - -const int SQLITE_CORRUPT = 11; - -const int SQLITE_NOTFOUND = 12; - -const int SQLITE_FULL = 13; - -const int SQLITE_CANTOPEN = 14; - -const int SQLITE_PROTOCOL = 15; - -const int SQLITE_EMPTY = 16; - -const int SQLITE_SCHEMA = 17; - -const int SQLITE_TOOBIG = 18; - -const int SQLITE_CONSTRAINT = 19; - -const int SQLITE_MISMATCH = 20; - -const int SQLITE_MISUSE = 21; - -const int SQLITE_NOLFS = 22; - -const int SQLITE_AUTH = 23; - -const int SQLITE_FORMAT = 24; - -const int SQLITE_RANGE = 25; - -const int SQLITE_NOTADB = 26; - -const int SQLITE_NOTICE = 27; - -const int SQLITE_WARNING = 28; - -const int SQLITE_ROW = 100; - -const int SQLITE_DONE = 101; - -const int SQLITE_ERROR_MISSING_COLLSEQ = 257; - -const int SQLITE_ERROR_RETRY = 513; - -const int SQLITE_ERROR_SNAPSHOT = 769; - -const int SQLITE_IOERR_READ = 266; - -const int SQLITE_IOERR_SHORT_READ = 522; - -const int SQLITE_IOERR_WRITE = 778; - -const int SQLITE_IOERR_FSYNC = 1034; - -const int SQLITE_IOERR_DIR_FSYNC = 1290; - -const int SQLITE_IOERR_TRUNCATE = 1546; - -const int SQLITE_IOERR_FSTAT = 1802; - -const int SQLITE_IOERR_UNLOCK = 2058; - -const int SQLITE_IOERR_RDLOCK = 2314; - -const int SQLITE_IOERR_DELETE = 2570; - -const int SQLITE_IOERR_BLOCKED = 2826; - -const int SQLITE_IOERR_NOMEM = 3082; - -const int SQLITE_IOERR_ACCESS = 3338; - -const int SQLITE_IOERR_CHECKRESERVEDLOCK = 3594; - -const int SQLITE_IOERR_LOCK = 3850; - -const int SQLITE_IOERR_CLOSE = 4106; - -const int SQLITE_IOERR_DIR_CLOSE = 4362; - -const int SQLITE_IOERR_SHMOPEN = 4618; - -const int SQLITE_IOERR_SHMSIZE = 4874; - -const int SQLITE_IOERR_SHMLOCK = 5130; - -const int SQLITE_IOERR_SHMMAP = 5386; - -const int SQLITE_IOERR_SEEK = 5642; - -const int SQLITE_IOERR_DELETE_NOENT = 5898; - -const int SQLITE_IOERR_MMAP = 6154; - -const int SQLITE_IOERR_GETTEMPPATH = 6410; - -const int SQLITE_IOERR_CONVPATH = 6666; - -const int SQLITE_IOERR_VNODE = 6922; - -const int SQLITE_IOERR_AUTH = 7178; - -const int SQLITE_IOERR_BEGIN_ATOMIC = 7434; - -const int SQLITE_IOERR_COMMIT_ATOMIC = 7690; - -const int SQLITE_IOERR_ROLLBACK_ATOMIC = 7946; - -const int SQLITE_IOERR_DATA = 8202; - -const int SQLITE_LOCKED_SHAREDCACHE = 262; - -const int SQLITE_LOCKED_VTAB = 518; - -const int SQLITE_BUSY_RECOVERY = 261; - -const int SQLITE_BUSY_SNAPSHOT = 517; - -const int SQLITE_BUSY_TIMEOUT = 773; - -const int SQLITE_CANTOPEN_NOTEMPDIR = 270; - -const int SQLITE_CANTOPEN_ISDIR = 526; - -const int SQLITE_CANTOPEN_FULLPATH = 782; - -const int SQLITE_CANTOPEN_CONVPATH = 1038; - -const int SQLITE_CANTOPEN_DIRTYWAL = 1294; - -const int SQLITE_CANTOPEN_SYMLINK = 1550; - -const int SQLITE_CORRUPT_VTAB = 267; - -const int SQLITE_CORRUPT_SEQUENCE = 523; - -const int SQLITE_CORRUPT_INDEX = 779; - -const int SQLITE_READONLY_RECOVERY = 264; - -const int SQLITE_READONLY_CANTLOCK = 520; - -const int SQLITE_READONLY_ROLLBACK = 776; - -const int SQLITE_READONLY_DBMOVED = 1032; - -const int SQLITE_READONLY_CANTINIT = 1288; - -const int SQLITE_READONLY_DIRECTORY = 1544; - -const int SQLITE_ABORT_ROLLBACK = 516; - -const int SQLITE_CONSTRAINT_CHECK = 275; - -const int SQLITE_CONSTRAINT_COMMITHOOK = 531; - -const int SQLITE_CONSTRAINT_FOREIGNKEY = 787; - -const int SQLITE_CONSTRAINT_FUNCTION = 1043; - -const int SQLITE_CONSTRAINT_NOTNULL = 1299; - -const int SQLITE_CONSTRAINT_PRIMARYKEY = 1555; - -const int SQLITE_CONSTRAINT_TRIGGER = 1811; - -const int SQLITE_CONSTRAINT_UNIQUE = 2067; - -const int SQLITE_CONSTRAINT_VTAB = 2323; - -const int SQLITE_CONSTRAINT_ROWID = 2579; - -const int SQLITE_CONSTRAINT_PINNED = 2835; - -const int SQLITE_NOTICE_RECOVER_WAL = 283; - -const int SQLITE_NOTICE_RECOVER_ROLLBACK = 539; - -const int SQLITE_WARNING_AUTOINDEX = 284; - -const int SQLITE_AUTH_USER = 279; - -const int SQLITE_OK_LOAD_PERMANENTLY = 256; - -const int SQLITE_OK_SYMLINK = 512; - -const int SQLITE_OPEN_READONLY = 1; - -const int SQLITE_OPEN_READWRITE = 2; - -const int SQLITE_OPEN_CREATE = 4; - -const int SQLITE_OPEN_DELETEONCLOSE = 8; - -const int SQLITE_OPEN_EXCLUSIVE = 16; - -const int SQLITE_OPEN_AUTOPROXY = 32; - -const int SQLITE_OPEN_URI = 64; - -const int SQLITE_OPEN_MEMORY = 128; - -const int SQLITE_OPEN_MAIN_DB = 256; - -const int SQLITE_OPEN_TEMP_DB = 512; - -const int SQLITE_OPEN_TRANSIENT_DB = 1024; - -const int SQLITE_OPEN_MAIN_JOURNAL = 2048; - -const int SQLITE_OPEN_TEMP_JOURNAL = 4096; - -const int SQLITE_OPEN_SUBJOURNAL = 8192; - -const int SQLITE_OPEN_MASTER_JOURNAL = 16384; - -const int SQLITE_OPEN_NOMUTEX = 32768; - -const int SQLITE_OPEN_FULLMUTEX = 65536; - -const int SQLITE_OPEN_SHAREDCACHE = 131072; - -const int SQLITE_OPEN_PRIVATECACHE = 262144; - -const int SQLITE_OPEN_WAL = 524288; - -const int SQLITE_OPEN_NOFOLLOW = 16777216; - -const int SQLITE_IOCAP_ATOMIC = 1; - -const int SQLITE_IOCAP_ATOMIC512 = 2; - -const int SQLITE_IOCAP_ATOMIC1K = 4; - -const int SQLITE_IOCAP_ATOMIC2K = 8; - -const int SQLITE_IOCAP_ATOMIC4K = 16; - -const int SQLITE_IOCAP_ATOMIC8K = 32; - -const int SQLITE_IOCAP_ATOMIC16K = 64; - -const int SQLITE_IOCAP_ATOMIC32K = 128; - -const int SQLITE_IOCAP_ATOMIC64K = 256; - -const int SQLITE_IOCAP_SAFE_APPEND = 512; - -const int SQLITE_IOCAP_SEQUENTIAL = 1024; - -const int SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 2048; - -const int SQLITE_IOCAP_POWERSAFE_OVERWRITE = 4096; - -const int SQLITE_IOCAP_IMMUTABLE = 8192; - -const int SQLITE_IOCAP_BATCH_ATOMIC = 16384; - -const int SQLITE_LOCK_NONE = 0; - -const int SQLITE_LOCK_SHARED = 1; - -const int SQLITE_LOCK_RESERVED = 2; - -const int SQLITE_LOCK_PENDING = 3; - -const int SQLITE_LOCK_EXCLUSIVE = 4; - -const int SQLITE_SYNC_NORMAL = 2; - -const int SQLITE_SYNC_FULL = 3; - -const int SQLITE_SYNC_DATAONLY = 16; - -const int SQLITE_FCNTL_LOCKSTATE = 1; - -const int SQLITE_FCNTL_GET_LOCKPROXYFILE = 2; - -const int SQLITE_FCNTL_SET_LOCKPROXYFILE = 3; - -const int SQLITE_FCNTL_LAST_ERRNO = 4; - -const int SQLITE_FCNTL_SIZE_HINT = 5; - -const int SQLITE_FCNTL_CHUNK_SIZE = 6; - -const int SQLITE_FCNTL_FILE_POINTER = 7; - -const int SQLITE_FCNTL_SYNC_OMITTED = 8; - -const int SQLITE_FCNTL_WIN32_AV_RETRY = 9; - -const int SQLITE_FCNTL_PERSIST_WAL = 10; - -const int SQLITE_FCNTL_OVERWRITE = 11; - -const int SQLITE_FCNTL_VFSNAME = 12; - -const int SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13; - -const int SQLITE_FCNTL_PRAGMA = 14; - -const int SQLITE_FCNTL_BUSYHANDLER = 15; - -const int SQLITE_FCNTL_TEMPFILENAME = 16; - -const int SQLITE_FCNTL_MMAP_SIZE = 18; - -const int SQLITE_FCNTL_TRACE = 19; - -const int SQLITE_FCNTL_HAS_MOVED = 20; - -const int SQLITE_FCNTL_SYNC = 21; - -const int SQLITE_FCNTL_COMMIT_PHASETWO = 22; - -const int SQLITE_FCNTL_WIN32_SET_HANDLE = 23; - -const int SQLITE_FCNTL_WAL_BLOCK = 24; - -const int SQLITE_FCNTL_ZIPVFS = 25; - -const int SQLITE_FCNTL_RBU = 26; - -const int SQLITE_FCNTL_VFS_POINTER = 27; - -const int SQLITE_FCNTL_JOURNAL_POINTER = 28; - -const int SQLITE_FCNTL_WIN32_GET_HANDLE = 29; - -const int SQLITE_FCNTL_PDB = 30; - -const int SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = 31; - -const int SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = 32; - -const int SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = 33; - -const int SQLITE_FCNTL_LOCK_TIMEOUT = 34; - -const int SQLITE_FCNTL_DATA_VERSION = 35; - -const int SQLITE_FCNTL_SIZE_LIMIT = 36; - -const int SQLITE_FCNTL_CKPT_DONE = 37; - -const int SQLITE_FCNTL_RESERVE_BYTES = 38; - -const int SQLITE_FCNTL_CKPT_START = 39; - -const int SQLITE_GET_LOCKPROXYFILE = 2; - -const int SQLITE_SET_LOCKPROXYFILE = 3; - -const int SQLITE_LAST_ERRNO = 4; - -const int SQLITE_ACCESS_EXISTS = 0; - -const int SQLITE_ACCESS_READWRITE = 1; - -const int SQLITE_ACCESS_READ = 2; - -const int SQLITE_SHM_UNLOCK = 1; - -const int SQLITE_SHM_LOCK = 2; - -const int SQLITE_SHM_SHARED = 4; - -const int SQLITE_SHM_EXCLUSIVE = 8; - -const int SQLITE_SHM_NLOCK = 8; - -const int SQLITE_CONFIG_SINGLETHREAD = 1; - -const int SQLITE_CONFIG_MULTITHREAD = 2; - -const int SQLITE_CONFIG_SERIALIZED = 3; - -const int SQLITE_CONFIG_MALLOC = 4; - -const int SQLITE_CONFIG_GETMALLOC = 5; - -const int SQLITE_CONFIG_SCRATCH = 6; - -const int SQLITE_CONFIG_PAGECACHE = 7; - -const int SQLITE_CONFIG_HEAP = 8; - -const int SQLITE_CONFIG_MEMSTATUS = 9; - -const int SQLITE_CONFIG_MUTEX = 10; - -const int SQLITE_CONFIG_GETMUTEX = 11; - -const int SQLITE_CONFIG_LOOKASIDE = 13; - -const int SQLITE_CONFIG_PCACHE = 14; - -const int SQLITE_CONFIG_GETPCACHE = 15; - -const int SQLITE_CONFIG_LOG = 16; - -const int SQLITE_CONFIG_URI = 17; - -const int SQLITE_CONFIG_PCACHE2 = 18; - -const int SQLITE_CONFIG_GETPCACHE2 = 19; - -const int SQLITE_CONFIG_COVERING_INDEX_SCAN = 20; - -const int SQLITE_CONFIG_SQLLOG = 21; - -const int SQLITE_CONFIG_MMAP_SIZE = 22; - -const int SQLITE_CONFIG_WIN32_HEAPSIZE = 23; - -const int SQLITE_CONFIG_PCACHE_HDRSZ = 24; - -const int SQLITE_CONFIG_PMASZ = 25; - -const int SQLITE_CONFIG_STMTJRNL_SPILL = 26; - -const int SQLITE_CONFIG_SMALL_MALLOC = 27; - -const int SQLITE_CONFIG_SORTERREF_SIZE = 28; - -const int SQLITE_CONFIG_MEMDB_MAXSIZE = 29; - -const int SQLITE_DBCONFIG_MAINDBNAME = 1000; - -const int SQLITE_DBCONFIG_LOOKASIDE = 1001; - -const int SQLITE_DBCONFIG_ENABLE_FKEY = 1002; - -const int SQLITE_DBCONFIG_ENABLE_TRIGGER = 1003; - -const int SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER = 1004; - -const int SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION = 1005; - -const int SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE = 1006; - -const int SQLITE_DBCONFIG_ENABLE_QPSG = 1007; - -const int SQLITE_DBCONFIG_TRIGGER_EQP = 1008; - -const int SQLITE_DBCONFIG_RESET_DATABASE = 1009; - -const int SQLITE_DBCONFIG_DEFENSIVE = 1010; - -const int SQLITE_DBCONFIG_WRITABLE_SCHEMA = 1011; - -const int SQLITE_DBCONFIG_LEGACY_ALTER_TABLE = 1012; - -const int SQLITE_DBCONFIG_DQS_DML = 1013; - -const int SQLITE_DBCONFIG_DQS_DDL = 1014; - -const int SQLITE_DBCONFIG_ENABLE_VIEW = 1015; - -const int SQLITE_DBCONFIG_LEGACY_FILE_FORMAT = 1016; - -const int SQLITE_DBCONFIG_TRUSTED_SCHEMA = 1017; - -const int SQLITE_DBCONFIG_MAX = 1017; - -const int SQLITE_DENY = 1; - -const int SQLITE_IGNORE = 2; - -const int SQLITE_CREATE_INDEX = 1; - -const int SQLITE_CREATE_TABLE = 2; - -const int SQLITE_CREATE_TEMP_INDEX = 3; - -const int SQLITE_CREATE_TEMP_TABLE = 4; - -const int SQLITE_CREATE_TEMP_TRIGGER = 5; - -const int SQLITE_CREATE_TEMP_VIEW = 6; - -const int SQLITE_CREATE_TRIGGER = 7; - -const int SQLITE_CREATE_VIEW = 8; - -const int SQLITE_DELETE = 9; - -const int SQLITE_DROP_INDEX = 10; - -const int SQLITE_DROP_TABLE = 11; - -const int SQLITE_DROP_TEMP_INDEX = 12; - -const int SQLITE_DROP_TEMP_TABLE = 13; - -const int SQLITE_DROP_TEMP_TRIGGER = 14; - -const int SQLITE_DROP_TEMP_VIEW = 15; - -const int SQLITE_DROP_TRIGGER = 16; - -const int SQLITE_DROP_VIEW = 17; - -const int SQLITE_INSERT = 18; - -const int SQLITE_PRAGMA = 19; - -const int SQLITE_READ = 20; - -const int SQLITE_SELECT = 21; - -const int SQLITE_TRANSACTION = 22; - -const int SQLITE_UPDATE = 23; - -const int SQLITE_ATTACH = 24; - -const int SQLITE_DETACH = 25; - -const int SQLITE_ALTER_TABLE = 26; - -const int SQLITE_REINDEX = 27; - -const int SQLITE_ANALYZE = 28; - -const int SQLITE_CREATE_VTABLE = 29; - -const int SQLITE_DROP_VTABLE = 30; - -const int SQLITE_FUNCTION = 31; - -const int SQLITE_SAVEPOINT = 32; - -const int SQLITE_COPY = 0; - -const int SQLITE_RECURSIVE = 33; - -const int SQLITE_TRACE_STMT = 1; - -const int SQLITE_TRACE_PROFILE = 2; - -const int SQLITE_TRACE_ROW = 4; - -const int SQLITE_TRACE_CLOSE = 8; - -const int SQLITE_LIMIT_LENGTH = 0; - -const int SQLITE_LIMIT_SQL_LENGTH = 1; - -const int SQLITE_LIMIT_COLUMN = 2; - -const int SQLITE_LIMIT_EXPR_DEPTH = 3; - -const int SQLITE_LIMIT_COMPOUND_SELECT = 4; - -const int SQLITE_LIMIT_VDBE_OP = 5; - -const int SQLITE_LIMIT_FUNCTION_ARG = 6; - -const int SQLITE_LIMIT_ATTACHED = 7; - -const int SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8; - -const int SQLITE_LIMIT_VARIABLE_NUMBER = 9; - -const int SQLITE_LIMIT_TRIGGER_DEPTH = 10; - -const int SQLITE_LIMIT_WORKER_THREADS = 11; - -const int SQLITE_PREPARE_PERSISTENT = 1; - -const int SQLITE_PREPARE_NORMALIZE = 2; - -const int SQLITE_PREPARE_NO_VTAB = 4; - -const int SQLITE_INTEGER = 1; - -const int SQLITE_FLOAT = 2; - -const int SQLITE_BLOB = 4; - -const int SQLITE_NULL = 5; - -const int SQLITE_TEXT = 3; - -const int SQLITE3_TEXT = 3; - -const int SQLITE_UTF8 = 1; - -const int SQLITE_UTF16LE = 2; - -const int SQLITE_UTF16BE = 3; - -const int SQLITE_UTF16 = 4; - -const int SQLITE_ANY = 5; - -const int SQLITE_UTF16_ALIGNED = 8; - -const int SQLITE_DETERMINISTIC = 2048; - -const int SQLITE_DIRECTONLY = 524288; - -const int SQLITE_SUBTYPE = 1048576; - -const int SQLITE_INNOCUOUS = 2097152; - -const int SQLITE_WIN32_DATA_DIRECTORY_TYPE = 1; - -const int SQLITE_WIN32_TEMP_DIRECTORY_TYPE = 2; - -const int SQLITE_INDEX_SCAN_UNIQUE = 1; - -const int SQLITE_INDEX_CONSTRAINT_EQ = 2; - -const int SQLITE_INDEX_CONSTRAINT_GT = 4; - -const int SQLITE_INDEX_CONSTRAINT_LE = 8; - -const int SQLITE_INDEX_CONSTRAINT_LT = 16; - -const int SQLITE_INDEX_CONSTRAINT_GE = 32; - -const int SQLITE_INDEX_CONSTRAINT_MATCH = 64; - -const int SQLITE_INDEX_CONSTRAINT_LIKE = 65; - -const int SQLITE_INDEX_CONSTRAINT_GLOB = 66; - -const int SQLITE_INDEX_CONSTRAINT_REGEXP = 67; - -const int SQLITE_INDEX_CONSTRAINT_NE = 68; - -const int SQLITE_INDEX_CONSTRAINT_ISNOT = 69; - -const int SQLITE_INDEX_CONSTRAINT_ISNOTNULL = 70; - -const int SQLITE_INDEX_CONSTRAINT_ISNULL = 71; - -const int SQLITE_INDEX_CONSTRAINT_IS = 72; - -const int SQLITE_INDEX_CONSTRAINT_FUNCTION = 150; - -const int SQLITE_MUTEX_FAST = 0; - -const int SQLITE_MUTEX_RECURSIVE = 1; - -const int SQLITE_MUTEX_STATIC_MASTER = 2; - -const int SQLITE_MUTEX_STATIC_MEM = 3; - -const int SQLITE_MUTEX_STATIC_MEM2 = 4; - -const int SQLITE_MUTEX_STATIC_OPEN = 4; - -const int SQLITE_MUTEX_STATIC_PRNG = 5; - -const int SQLITE_MUTEX_STATIC_LRU = 6; - -const int SQLITE_MUTEX_STATIC_LRU2 = 7; - -const int SQLITE_MUTEX_STATIC_PMEM = 7; - -const int SQLITE_MUTEX_STATIC_APP1 = 8; - -const int SQLITE_MUTEX_STATIC_APP2 = 9; - -const int SQLITE_MUTEX_STATIC_APP3 = 10; - -const int SQLITE_MUTEX_STATIC_VFS1 = 11; - -const int SQLITE_MUTEX_STATIC_VFS2 = 12; - -const int SQLITE_MUTEX_STATIC_VFS3 = 13; - -const int SQLITE_TESTCTRL_FIRST = 5; - -const int SQLITE_TESTCTRL_PRNG_SAVE = 5; - -const int SQLITE_TESTCTRL_PRNG_RESTORE = 6; - -const int SQLITE_TESTCTRL_PRNG_RESET = 7; - -const int SQLITE_TESTCTRL_BITVEC_TEST = 8; - -const int SQLITE_TESTCTRL_FAULT_INSTALL = 9; - -const int SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS = 10; - -const int SQLITE_TESTCTRL_PENDING_BYTE = 11; - -const int SQLITE_TESTCTRL_ASSERT = 12; - -const int SQLITE_TESTCTRL_ALWAYS = 13; - -const int SQLITE_TESTCTRL_RESERVE = 14; - -const int SQLITE_TESTCTRL_OPTIMIZATIONS = 15; - -const int SQLITE_TESTCTRL_ISKEYWORD = 16; - -const int SQLITE_TESTCTRL_SCRATCHMALLOC = 17; - -const int SQLITE_TESTCTRL_INTERNAL_FUNCTIONS = 17; - -const int SQLITE_TESTCTRL_LOCALTIME_FAULT = 18; - -const int SQLITE_TESTCTRL_EXPLAIN_STMT = 19; - -const int SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD = 19; - -const int SQLITE_TESTCTRL_NEVER_CORRUPT = 20; - -const int SQLITE_TESTCTRL_VDBE_COVERAGE = 21; - -const int SQLITE_TESTCTRL_BYTEORDER = 22; - -const int SQLITE_TESTCTRL_ISINIT = 23; - -const int SQLITE_TESTCTRL_SORTER_MMAP = 24; - -const int SQLITE_TESTCTRL_IMPOSTER = 25; - -const int SQLITE_TESTCTRL_PARSER_COVERAGE = 26; - -const int SQLITE_TESTCTRL_RESULT_INTREAL = 27; - -const int SQLITE_TESTCTRL_PRNG_SEED = 28; - -const int SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS = 29; - -const int SQLITE_TESTCTRL_LAST = 29; - -const int SQLITE_STATUS_MEMORY_USED = 0; - -const int SQLITE_STATUS_PAGECACHE_USED = 1; - -const int SQLITE_STATUS_PAGECACHE_OVERFLOW = 2; - -const int SQLITE_STATUS_SCRATCH_USED = 3; - -const int SQLITE_STATUS_SCRATCH_OVERFLOW = 4; - -const int SQLITE_STATUS_MALLOC_SIZE = 5; - -const int SQLITE_STATUS_PARSER_STACK = 6; - -const int SQLITE_STATUS_PAGECACHE_SIZE = 7; - -const int SQLITE_STATUS_SCRATCH_SIZE = 8; - -const int SQLITE_STATUS_MALLOC_COUNT = 9; - -const int SQLITE_DBSTATUS_LOOKASIDE_USED = 0; - -const int SQLITE_DBSTATUS_CACHE_USED = 1; - -const int SQLITE_DBSTATUS_SCHEMA_USED = 2; - -const int SQLITE_DBSTATUS_STMT_USED = 3; - -const int SQLITE_DBSTATUS_LOOKASIDE_HIT = 4; - -const int SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE = 5; - -const int SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL = 6; - -const int SQLITE_DBSTATUS_CACHE_HIT = 7; - -const int SQLITE_DBSTATUS_CACHE_MISS = 8; - -const int SQLITE_DBSTATUS_CACHE_WRITE = 9; - -const int SQLITE_DBSTATUS_DEFERRED_FKS = 10; - -const int SQLITE_DBSTATUS_CACHE_USED_SHARED = 11; - -const int SQLITE_DBSTATUS_CACHE_SPILL = 12; - -const int SQLITE_DBSTATUS_MAX = 12; - -const int SQLITE_STMTSTATUS_FULLSCAN_STEP = 1; - -const int SQLITE_STMTSTATUS_SORT = 2; - -const int SQLITE_STMTSTATUS_AUTOINDEX = 3; - -const int SQLITE_STMTSTATUS_VM_STEP = 4; - -const int SQLITE_STMTSTATUS_REPREPARE = 5; - -const int SQLITE_STMTSTATUS_RUN = 6; - -const int SQLITE_STMTSTATUS_MEMUSED = 99; - -const int SQLITE_CHECKPOINT_PASSIVE = 0; - -const int SQLITE_CHECKPOINT_FULL = 1; - -const int SQLITE_CHECKPOINT_RESTART = 2; - -const int SQLITE_CHECKPOINT_TRUNCATE = 3; - -const int SQLITE_VTAB_CONSTRAINT_SUPPORT = 1; - -const int SQLITE_VTAB_INNOCUOUS = 2; - -const int SQLITE_VTAB_DIRECTONLY = 3; - -const int SQLITE_ROLLBACK = 1; - -const int SQLITE_FAIL = 3; - -const int SQLITE_REPLACE = 5; - -const int SQLITE_SCANSTAT_NLOOP = 0; - -const int SQLITE_SCANSTAT_NVISIT = 1; - -const int SQLITE_SCANSTAT_EST = 2; - -const int SQLITE_SCANSTAT_NAME = 3; - -const int SQLITE_SCANSTAT_EXPLAIN = 4; - -const int SQLITE_SCANSTAT_SELECTID = 5; - -const int SQLITE_SERIALIZE_NOCOPY = 1; - -const int SQLITE_DESERIALIZE_FREEONCLOSE = 1; - -const int SQLITE_DESERIALIZE_RESIZEABLE = 2; - -const int SQLITE_DESERIALIZE_READONLY = 4; - -const int NOT_WITHIN = 0; - -const int PARTLY_WITHIN = 1; - -const int FULLY_WITHIN = 2; - -const int FTS5_TOKENIZE_QUERY = 1; - -const int FTS5_TOKENIZE_PREFIX = 2; - -const int FTS5_TOKENIZE_DOCUMENT = 4; - -const int FTS5_TOKENIZE_AUX = 8; - -const int FTS5_TOKEN_COLOCATED = 1; - -typedef _c_sqlite3_close_v2 = ffi.Int32 Function( - ffi.Pointer<sqlite3> arg0, -); - -typedef _dart_sqlite3_close_v2 = int Function( - ffi.Pointer<sqlite3> arg0, -); - -typedef _c_sqlite3_open_v2 = ffi.Int32 Function( - ffi.Pointer<ffi.Int8> filename, - ffi.Pointer<ffi.Pointer<sqlite3>> ppDb, - ffi.Int32 flags, - ffi.Pointer<ffi.Int8> zVfs, -); - -typedef _dart_sqlite3_open_v2 = int Function( - ffi.Pointer<ffi.Int8> filename, - ffi.Pointer<ffi.Pointer<sqlite3>> ppDb, - int flags, - ffi.Pointer<ffi.Int8> zVfs, -); - -typedef _c_sqlite3_errmsg = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3> arg0, -); - -typedef _dart_sqlite3_errmsg = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3> arg0, -); - -typedef _c_sqlite3_errstr = ffi.Pointer<ffi.Int8> Function( - ffi.Int32 arg0, -); - -typedef _dart_sqlite3_errstr = ffi.Pointer<ffi.Int8> Function( - int arg0, -); - -typedef _c_sqlite3_prepare_v2 = ffi.Int32 Function( - ffi.Pointer<sqlite3> db, - ffi.Pointer<ffi.Int8> zSql, - ffi.Int32 nByte, - ffi.Pointer<ffi.Pointer<sqlite3_stmt>> ppStmt, - ffi.Pointer<ffi.Pointer<ffi.Int8>> pzTail, -); - -typedef _dart_sqlite3_prepare_v2 = int Function( - ffi.Pointer<sqlite3> db, - ffi.Pointer<ffi.Int8> zSql, - int nByte, - ffi.Pointer<ffi.Pointer<sqlite3_stmt>> ppStmt, - ffi.Pointer<ffi.Pointer<ffi.Int8>> pzTail, -); - -typedef _c_sqlite3_column_count = ffi.Int32 Function( - ffi.Pointer<sqlite3_stmt> pStmt, -); - -typedef _dart_sqlite3_column_count = int Function( - ffi.Pointer<sqlite3_stmt> pStmt, -); - -typedef _c_sqlite3_column_name = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - ffi.Int32 N, -); - -typedef _dart_sqlite3_column_name = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - int N, -); - -typedef _c_sqlite3_column_decltype = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - ffi.Int32 arg1, -); - -typedef _dart_sqlite3_column_decltype = ffi.Pointer<ffi.Int8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - int arg1, -); - -typedef _c_sqlite3_step = ffi.Int32 Function( - ffi.Pointer<sqlite3_stmt> arg0, -); - -typedef _dart_sqlite3_step = int Function( - ffi.Pointer<sqlite3_stmt> arg0, -); - -typedef _c_sqlite3_column_int = ffi.Int32 Function( - ffi.Pointer<sqlite3_stmt> arg0, - ffi.Int32 iCol, -); - -typedef _dart_sqlite3_column_int = int Function( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, -); - -typedef _c_sqlite3_column_text = ffi.Pointer<ffi.Uint8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - ffi.Int32 iCol, -); - -typedef _dart_sqlite3_column_text = ffi.Pointer<ffi.Uint8> Function( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, -); - -typedef _c_sqlite3_column_type = ffi.Int32 Function( - ffi.Pointer<sqlite3_stmt> arg0, - ffi.Int32 iCol, -); - -typedef _dart_sqlite3_column_type = int Function( - ffi.Pointer<sqlite3_stmt> arg0, - int iCol, -); - -typedef _c_sqlite3_finalize = ffi.Int32 Function( - ffi.Pointer<sqlite3_stmt> pStmt, -); - -typedef _dart_sqlite3_finalize = int Function( - ffi.Pointer<sqlite3_stmt> pStmt, -); - -typedef _typedefC_1 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, -); - -typedef _typedefC_2 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Pointer<ffi.Void>, - ffi.Int32, - ffi.Int64, -); - -typedef _typedefC_3 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Pointer<ffi.Void>, - ffi.Int32, - ffi.Int64, -); - -typedef _typedefC_4 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int64, -); - -typedef _typedefC_5 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, -); - -typedef _typedefC_6 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Pointer<ffi.Int64>, -); - -typedef _typedefC_7 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, -); - -typedef _typedefC_8 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, -); - -typedef _typedefC_9 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Pointer<ffi.Int32>, -); - -typedef _typedefC_10 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, - ffi.Pointer<ffi.Void>, -); - -typedef _typedefC_11 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, -); - -typedef _typedefC_12 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, -); - -typedef _typedefC_13 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, - ffi.Int32, - ffi.Int32, - ffi.Pointer<ffi.Pointer<ffi.Void>>, -); - -typedef _typedefC_14 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, - ffi.Int32, - ffi.Int32, -); - -typedef _typedefC_15 = ffi.Void Function( - ffi.Pointer<sqlite3_file>, -); - -typedef _typedefC_16 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int32, -); - -typedef _typedefC_17 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int64, - ffi.Int32, - ffi.Pointer<ffi.Pointer<ffi.Void>>, -); - -typedef _typedefC_18 = ffi.Int32 Function( - ffi.Pointer<sqlite3_file>, - ffi.Int64, - ffi.Pointer<ffi.Void>, -);
diff --git a/samples/ffi/sqlite/pubspec.yaml b/samples/ffi/sqlite/pubspec.yaml index b70a25a..dcc5d40 100644 --- a/samples/ffi/sqlite/pubspec.yaml +++ b/samples/ffi/sqlite/pubspec.yaml
@@ -1,55 +1,11 @@ name: sqlite3 - version: 0.0.1 - description: >- Sqlite3 wrapper. Demo for dart:ffi. - author: Daco Harkes <dacoharkes@google.com>, Samir Jindel <sjindel@google.com> - environment: sdk: '>=2.1.0 <3.0.0' - dependencies: ffi: ^0.1.3 - dev_dependencies: test: ^1.5.3 - ffigen: ^0.2.0 - -ffigen: - name: SQLite - description: SQLite bindings. - output: 'lib/src/third_party/sqlite/sqlite3_bindings_generated.dart' - headers: - entry-points: - - '/usr/include/sqlite3.h' - include-directives: - - '**sqlite3.h' - functions: - include: - - sqlite3_close_v2 - - sqlite3_column_count - - sqlite3_column_decltype - - sqlite3_column_int - - sqlite3_column_name - - sqlite3_column_text - - sqlite3_column_type - - sqlite3_errmsg - - sqlite3_errstr - - sqlite3_finalize - - sqlite3_open_v2 - - sqlite3_prepare_v2 - - sqlite3_step - comments: - style: any - length: full - preamble: | - // 2001 September 15 - // - // The author disclaims copyright to this source code. In place of - // a legal notice, here is a blessing: - // - // May you do good and not evil. - // May you find forgiveness for yourself and forgive others. - // May you share freely, never taking more than you give.
diff --git a/samples/ffi/sqlite/test/sqlite_test.dart b/samples/ffi/sqlite/test/sqlite_test.dart index 7b36917..7bef552 100644 --- a/samples/ffi/sqlite/test/sqlite_test.dart +++ b/samples/ffi/sqlite/test/sqlite_test.dart
@@ -13,7 +13,6 @@ import '../lib/sqlite.dart'; void main() { - assert(Platform.script.hasAbsolutePath); // `pub run test` is broken. final dbPath = Platform.script.resolve("test.db").path; test("sqlite integration test", () { Database d = Database(dbPath); @@ -167,7 +166,6 @@ r.close(); d.close(); }); - test("Utf8 unit test", () { final String test = 'Hasta Mañana'; final medium = Utf8.toUtf8(test);
diff --git a/tests/language/unsorted/external_test.dart b/tests/language/unsorted/external_test.dart index 8418280..12d6306c 100644 --- a/tests/language/unsorted/external_test.dart +++ b/tests/language/unsorted/external_test.dart
@@ -15,8 +15,6 @@ Foo() : x = 0; //^^^ // [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD -//^^^ -// [analyzer] COMPILE_TIME_ERROR.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD external var x01; external int x02; @@ -69,13 +67,13 @@ } external int t06(int i) { return 1; } -// [error line 71, column 1, length 8] +// [error line 69, column 1, length 8] // [analyzer] SYNTACTIC_ERROR.EXTERNAL_METHOD_WITH_BODY // [cfe] An external or native method can't have a body. // ^ // [cfe] An external or native method can't have a body. external int t07(int i) => i + 1; -// [error line 77, column 1, length 8] +// [error line 75, column 1, length 8] // [analyzer] SYNTACTIC_ERROR.EXTERNAL_METHOD_WITH_BODY // [cfe] An external or native method can't have a body. // ^
diff --git a/third_party/.gitignore b/third_party/.gitignore index ced573a..0bd8a83 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -13,6 +13,5 @@ !unittest.tar.gz.sha1 !update.sh !/wasmer -!/sqlite # but ignore a subfolder of tcmalloc (some client ignores /tcmalloc/.gitignore) /tcmalloc/gperftools
diff --git a/third_party/sqlite/LICENSE.md b/third_party/sqlite/LICENSE.md deleted file mode 100644 index f677190..0000000 --- a/third_party/sqlite/LICENSE.md +++ /dev/null
@@ -1,9 +0,0 @@ -The author disclaims copyright to this source code. In place of -a legal notice, here is a blessing: - - * May you do good and not evil. - * May you find forgiveness for yourself and forgive others. - * May you share freely, never taking more than you give. - -Files generated from sqlite source files are in -samples/ffi/sqlite/lib/src/third_party/sqlite.
diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml index 9f08f16..bfe6172 100644 --- a/third_party/wasmer/Cargo.toml +++ b/third_party/wasmer/Cargo.toml
@@ -1,6 +1,6 @@ [package] name = "wasmer" -version = "0.7.0" +version = "0.17.1" [lib] name = "wasmer" @@ -8,4 +8,4 @@ path = "wasmer.rs" [dependencies] -wasmer-runtime-c-api = "0.7.0" +wasmer-runtime-c-api = "0.17.1"
diff --git a/third_party/wasmer/LICENSE b/third_party/wasmer/LICENSE index 079740d..62bb543 100644 --- a/third_party/wasmer/LICENSE +++ b/third_party/wasmer/LICENSE
@@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Wasmer, Inc. and its affiliates. +Copyright (c) 2019-present Wasmer, Inc. and its affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
diff --git a/third_party/wasmer/README.md b/third_party/wasmer/README.md index 1e741cf..d1475b7 100644 --- a/third_party/wasmer/README.md +++ b/third_party/wasmer/README.md
@@ -1,31 +1,31 @@ <p align="center"> <a href="https://wasmer.io" target="_blank" rel="noopener noreferrer"> - <img width="400" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/logo.png" alt="Wasmer logo"> + <img width="300" src="https://raw.githubusercontent.com/wasmerio/wasmer/master/assets/logo.png" alt="Wasmer logo"> </a> </p> <p align="center"> - <a href="https://circleci.com/gh/wasmerio/wasmer/"> - <img src="https://img.shields.io/circleci/project/github/wasmerio/wasmer/master.svg" alt="Build Status"> + <a href="https://dev.azure.com/wasmerio/wasmer/_build/latest?definitionId=3&branchName=master"> + <img src="https://img.shields.io/azure-devops/build/wasmerio/wasmer/3.svg?style=flat-square" alt="Build Status"> </a> <a href="https://github.com/wasmerio/wasmer/blob/master/LICENSE"> - <img src="https://img.shields.io/github/license/wasmerio/wasmer.svg" alt="License"> + <img src="https://img.shields.io/github/license/wasmerio/wasmer.svg?style=flat-square" alt="License"> </a> <a href="https://spectrum.chat/wasmer"> <img src="https://withspectrum.github.io/badge/badge.svg" alt="Join the Wasmer Community"> </a> <a href="https://crates.io/crates/wasmer-runtime-c-api"> - <img src="https://img.shields.io/crates/d/wasmer-runtime-c-api.svg" alt="Number of downloads from crates.io"> + <img src="https://img.shields.io/crates/d/wasmer-runtime-c-api.svg?style=flat-square" alt="Number of downloads from crates.io"> </a> - <a href="https://docs.rs/wasmer-runtime-c-api"> - <img src="https://docs.rs/wasmer-runtime-c-api/badge.svg" alt="Read our API documentation"> + <a href="https://wasmerio.github.io/wasmer/c/runtime-c-api/"> + <img src="https://img.shields.io/badge/Docs-Wasmer%20C%20API-blue?style=flat-square" alt="Wasmer C API Documentation"> </a> </p> # Wasmer Runtime C API Wasmer is a standalone JIT WebAssembly runtime, aiming to be fully -compatible with Emscripten, Rust and Go. [Learn +compatible with WASI, Emscripten, Rust and Go. [Learn more](https://github.com/wasmerio/wasmer). This crate exposes a C and a C++ API for the Wasmer runtime. @@ -36,6 +36,10 @@ crate, respectively [`wasmer.h`][wasmer_h] and [`wasmer.hh`][wasmer_hh]. They are automatically generated, and always up-to-date in this repository. +The runtime shared library (so, dll, dylib) can also be downloaded in Wasmer [release page](https://github.com/wasmerio/wasmer/releases). + +You can find the full C API documentation here: +https://wasmerio.github.io/wasmer/c/runtime-c-api/ Here is a simple example to use the C API: @@ -104,10 +108,14 @@ # Testing +Tests are run using the release build of the library. If you make +changes or compile with non-default features, please ensure you +rebuild in release mode for the tests to see the changes. + The tests can be run via `cargo test`, such as: ```sh -$ cargo test -- --nocapture +$ cargo test --release -- --nocapture ``` To run tests manually, enter the `lib/runtime-c-api/tests` directory
diff --git a/third_party/wasmer/wasmer.hh b/third_party/wasmer/wasmer.hh index cf7a1c7..647e637 100644 --- a/third_party/wasmer/wasmer.hh +++ b/third_party/wasmer/wasmer.hh
@@ -1,3 +1,36 @@ + +#if !defined(WASMER_H_MACROS) + +#define WASMER_H_MACROS + +// Define the `ARCH_X86_X64` constant. +#if defined(MSVC) && defined(_M_AMD64) +# define ARCH_X86_64 +#elif (defined(GCC) || defined(__GNUC__) || defined(__clang__)) && defined(__x86_64__) +# define ARCH_X86_64 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_attribute) +# define __has_attribute(x) 0 +#endif + +// Compatibility with non-Clang compilers. +#if !defined(__has_declspec_attribute) +# define __has_declspec_attribute(x) 0 +#endif + +// Define the `DEPRECATED` macro. +#if defined(GCC) || defined(__GNUC__) || __has_attribute(deprecated) +# define DEPRECATED(message) __attribute__((deprecated(message))) +#elif defined(MSVC) || __has_declspec_attribute(deprecated) +# define DEPRECATED(message) __declspec(deprecated(message)) +#endif + +#define WASMER_WASI_ENABLED +#endif // WASMER_H_MACROS + + #ifndef WASMER_H #define WASMER_H @@ -6,22 +39,52 @@ #include <cstdlib> #include <new> +#if defined(WASMER_WASI_ENABLED) +enum class Version : uint8_t { + /// Version cannot be detected or is unknown. + Unknown = 0, + /// Latest version. See `wasmer_wasi::WasiVersion::Latest` to + /// learn more. + Latest = 1, + /// `wasi_unstable`. + Snapshot0 = 2, + /// `wasi_snapshot_preview1`. + Snapshot1 = 3, +}; +#endif + +/// List of export/import kinds. enum class wasmer_import_export_kind : uint32_t { - WASM_FUNCTION, - WASM_GLOBAL, - WASM_MEMORY, - WASM_TABLE, + /// The export/import is a function. + WASM_FUNCTION = 0, + /// The export/import is a global. + WASM_GLOBAL = 1, + /// The export/import is a memory. + WASM_MEMORY = 2, + /// The export/import is a table. + WASM_TABLE = 3, }; +/// The `wasmer_result_t` enum is a type that represents either a +/// success, or a failure. enum class wasmer_result_t { + /// Represents a success. WASMER_OK = 1, + /// Represents a failure. WASMER_ERROR = 2, }; +/// Represents all possibles WebAssembly value types. +/// +/// See `wasmer_value_t` to get a complete example. enum class wasmer_value_tag : uint32_t { + /// Represents the `i32` WebAssembly type. WASM_I32, + /// Represents the `i64` WebAssembly type. WASM_I64, + /// Represents the `f32` WebAssembly type. WASM_F32, + /// Represents the `f64` WebAssembly type. WASM_F64, }; @@ -29,7 +92,12 @@ }; -struct wasmer_export_descriptor_t { +/// Opaque pointer to a `wasmer_runtime::Instance` value in Rust. +/// +/// A `wasmer_runtime::Instance` represents a WebAssembly instance. It +/// is generally generated by the `wasmer_instantiate()` function, or by +/// the `wasmer_module_instantiate()` function for the most common paths. +struct wasmer_instance_t { }; @@ -38,14 +106,38 @@ uint32_t bytes_len; }; +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Type used to construct an import_object_t with Emscripten imports. +struct wasmer_emscripten_globals_t { + +}; +#endif + +struct wasmer_import_object_t { + +}; + +/// Opaque pointer to `NamedExportDescriptor`. +struct wasmer_export_descriptor_t { + +}; + +/// Opaque pointer to `NamedExportDescriptors`. struct wasmer_export_descriptors_t { }; +/// Opaque pointer to `wasmer_export_t`. struct wasmer_export_func_t { }; +/// Represents a WebAssembly value. +/// +/// This is a [Rust union][rust-union], which is equivalent to the C +/// union. See `wasmer_value_t` to get a complete example. +/// +/// [rust-union]: https://doc.rust-lang.org/reference/items/unions.html union wasmer_value { int32_t I32; int64_t I64; @@ -53,19 +145,53 @@ double F64; }; +/// Represents a WebAssembly type and value pair, +/// i.e. `wasmer_value_tag` and `wasmer_value`. Since the latter is an +/// union, it's the safe way to read or write a WebAssembly value in +/// C. +/// +/// Example: +/// +/// ```c +/// // Create a WebAssembly value. +/// wasmer_value_t wasm_value = { +/// .tag = WASM_I32, +/// .value.I32 = 42, +/// }; +/// +/// // Read a WebAssembly value. +/// if (wasm_value.tag == WASM_I32) { +/// int32_t x = wasm_value.value.I32; +/// // … +/// } +/// ``` struct wasmer_value_t { + /// The value type. wasmer_value_tag tag; + /// The value. wasmer_value value; }; +/// Opaque pointer to `NamedExport`. struct wasmer_export_t { }; +/// Opaque pointer to a `wasmer_runtime::Memory` value in Rust. +/// +/// A `wasmer_runtime::Memory` represents a WebAssembly memory. It is +/// possible to create one with `wasmer_memory_new()` and pass it as +/// imports of an instance, or to read it from exports of an instance +/// with `wasmer_export_to_memory()`. struct wasmer_memory_t { }; +/// Opaque pointer to the opaque structure `crate::NamedExports`, +/// which is a wrapper around a vector of the opaque structure +/// `crate::NamedExport`. +/// +/// Check the `wasmer_instance_exports()` function to learn more. struct wasmer_exports_t { }; @@ -91,14 +217,11 @@ }; -struct wasmer_import_object_t { - -}; - struct wasmer_table_t { }; +/// Union of import/export value. union wasmer_import_export_value { const wasmer_import_func_t *func; const wasmer_table_t *table; @@ -113,21 +236,55 @@ wasmer_import_export_value value; }; -struct wasmer_instance_t { +struct wasmer_import_object_iter_t { }; +/// Opaque pointer to a `wasmer_runtime::Ctx` value in Rust. +/// +/// An instance context is passed to any host function (aka imported +/// function) as the first argument. It is necessary to read the +/// instance data or the memory, respectively with the +/// `wasmer_instance_context_data_get()` function, and the +/// `wasmer_instance_context_memory()` function. +/// +/// It is also possible to get the instance context outside a host +/// function by using the `wasmer_instance_context_get()` +/// function. See also `wasmer_instance_context_data_set()` to set the +/// instance context data. +/// +/// Example: +/// +/// ```c +/// // A host function that prints data from the WebAssembly memory to +/// // the standard output. +/// void print(wasmer_instance_context_t *context, int32_t pointer, int32_t length) { +/// // Use `wasmer_instance_context` to get back the first instance memory. +/// const wasmer_memory_t *memory = wasmer_instance_context_memory(context, 0); +/// +/// // Continue… +/// } +/// ``` struct wasmer_instance_context_t { }; +/// The `wasmer_limit_option_t` struct represents an optional limit +/// for `wasmer_limits_t`. struct wasmer_limit_option_t { + /// Whether the limit is set. bool has_some; + /// The limit value. uint32_t some; }; +/// The `wasmer_limits_t` struct is a type that describes a memory +/// options. See the `wasmer_memory_t` struct or the +/// `wasmer_memory_new()` function to get more information. struct wasmer_limits_t { + /// The minimum number of allowed pages. uint32_t min; + /// The maximum number of allowed pages. wasmer_limit_option_t max; }; @@ -135,28 +292,95 @@ }; +#if (!defined(_WIN32) && defined(ARCH_X86_64)) struct wasmer_trampoline_buffer_builder_t { }; +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) struct wasmer_trampoline_callable_t { }; +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) struct wasmer_trampoline_buffer_t { }; +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Opens a directory that's visible to the WASI module as `alias` but +/// is backed by the host file at `host_file_path` +struct wasmer_wasi_map_dir_entry_t { + /// What the WASI module will see in its virtual root + wasmer_byte_array alias; + /// The backing file that the WASI module will interact with via the alias + wasmer_byte_array host_file_path; +}; +#endif extern "C" { /// Creates a new Module from the given wasm bytes. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_compile(wasmer_module_t **module, uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Convenience function for setting up arguments and calling the Emscripten +/// main function. +/// +/// WARNING: +/// +/// Do not call this function on untrusted code when operating without +/// additional sandboxing in place. +/// Emscripten has access to many host system calls and therefore may do very +/// bad things. +wasmer_result_t wasmer_emscripten_call_main(wasmer_instance_t *instance, + const wasmer_byte_array *args, + unsigned int args_len); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Destroy `wasmer_emscrpten_globals_t` created by +/// `wasmer_emscripten_get_emscripten_globals`. +void wasmer_emscripten_destroy_globals(wasmer_emscripten_globals_t *globals); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Create a `wasmer_import_object_t` with Emscripten imports, use +/// `wasmer_emscripten_get_emscripten_globals` to get a +/// `wasmer_emscripten_globals_t` from a `wasmer_module_t`. +/// +/// WARNING: +/// +/// This `import_object_t` contains thin-wrappers around host system calls. +/// Do not use this to execute untrusted code without additional sandboxing. +wasmer_import_object_t *wasmer_emscripten_generate_import_object(wasmer_emscripten_globals_t *globals); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Create a `wasmer_emscripten_globals_t` from a Wasm module. +wasmer_emscripten_globals_t *wasmer_emscripten_get_globals(const wasmer_module_t *module); +#endif + +#if defined(WASMER_EMSCRIPTEN_ENABLED) +/// Execute global constructors (required if the module is compiled from C++) +/// and sets up the internal environment. +/// +/// This function sets the data pointer in the same way that +/// [`wasmer_instance_context_data_set`] does. +wasmer_result_t wasmer_emscripten_set_up(wasmer_instance_t *instance, + wasmer_emscripten_globals_t *globals); +#endif + /// Gets export descriptor kind wasmer_import_export_kind wasmer_export_descriptor_kind(wasmer_export_descriptor_t *export_); @@ -164,6 +388,7 @@ wasmer_byte_array wasmer_export_descriptor_name(wasmer_export_descriptor_t *export_descriptor); /// Gets export descriptors for the given module +/// /// The caller owns the object and should call `wasmer_export_descriptors_destroy` to free it. void wasmer_export_descriptors(const wasmer_module_t *module, wasmer_export_descriptors_t **export_descriptors); @@ -180,17 +405,21 @@ /// Calls a `func` with the provided parameters. /// Results are set using the provided `results` pointer. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_func_call(const wasmer_export_func_t *func, const wasmer_value_t *params, - int params_len, + unsigned int params_len, wasmer_value_t *results, - int results_len); + unsigned int results_len); /// Sets the params buffer to the parameter types of the given wasmer_export_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_func_params(const wasmer_export_func_t *func, @@ -198,13 +427,17 @@ uint32_t params_len); /// Sets the result parameter to the arity of the params of the wasmer_export_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_func_params_arity(const wasmer_export_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_export_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_func_returns(const wasmer_export_func_t *func, @@ -212,7 +445,9 @@ uint32_t returns_len); /// Sets the result parameter to the arity of the returns of the wasmer_export_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_func_returns_arity(const wasmer_export_func_t *func, @@ -228,12 +463,30 @@ const wasmer_export_func_t *wasmer_export_to_func(const wasmer_export_t *export_); /// Gets a memory pointer from an export pointer. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_export_to_memory(const wasmer_export_t *export_, wasmer_memory_t **memory); -/// Frees the memory for the given exports +/// Frees the memory for the given exports. +/// +/// Check the `wasmer_instance_exports()` function to get a complete +/// example. +/// +/// If `exports` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get some exports. +/// wasmer_exports_t *exports = NULL; +/// wasmer_instance_exports(instance, &exports); +/// +/// // Destroy the exports. +/// wasmer_exports_destroy(exports); +/// ``` void wasmer_exports_destroy(wasmer_exports_t *exports); /// Gets wasmer_export by index @@ -268,6 +521,7 @@ wasmer_byte_array wasmer_import_descriptor_name(wasmer_import_descriptor_t *import_descriptor); /// Gets import descriptors for the given module +/// /// The caller owns the object and should call `wasmer_import_descriptors_destroy` to free it. void wasmer_import_descriptors(const wasmer_module_t *module, wasmer_import_descriptors_t **import_descriptors); @@ -285,8 +539,23 @@ /// Frees memory for the given Func void wasmer_import_func_destroy(wasmer_import_func_t *func); -/// Creates new func -/// The caller owns the object and should call `wasmer_import_func_destroy` to free it. +/// Creates new host function, aka imported function. `func` is a +/// function pointer, where the first argument is the famous `vm::Ctx` +/// (in Rust), or `wasmer_instance_context_t` (in C). All arguments +/// must be typed with compatible WebAssembly native types: +/// +/// | WebAssembly type | C/C++ type | +/// | ---------------- | ---------- | +/// | `i32` | `int32_t` | +/// | `i64` | `int64_t` | +/// | `f32` | `float` | +/// | `f64` | `double` | +/// +/// The function pointer must have a lifetime greater than the +/// WebAssembly instance lifetime. +/// +/// The caller owns the object and should call +/// `wasmer_import_func_destroy` to free it. wasmer_import_func_t *wasmer_import_func_new(void (*func)(void *data), const wasmer_value_tag *params, unsigned int params_len, @@ -294,7 +563,9 @@ unsigned int returns_len); /// Sets the params buffer to the parameter types of the given wasmer_import_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_import_func_params(const wasmer_import_func_t *func, @@ -302,13 +573,17 @@ unsigned int params_len); /// Sets the result parameter to the arity of the params of the wasmer_import_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_import_func_params_arity(const wasmer_import_func_t *func, uint32_t *result); /// Sets the returns buffer to the parameter types of the given wasmer_import_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_import_func_returns(const wasmer_import_func_t *func, @@ -316,7 +591,9 @@ unsigned int returns_len); /// Sets the result parameter to the arity of the returns of the wasmer_import_func_t +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_import_func_returns_arity(const wasmer_import_func_t *func, @@ -327,18 +604,101 @@ /// Extends an existing import object with new imports wasmer_result_t wasmer_import_object_extend(wasmer_import_object_t *import_object, - wasmer_import_t *imports, + const wasmer_import_t *imports, unsigned int imports_len); +/// Gets an entry from an ImportObject at the name and namespace. +/// Stores `name`, `namespace`, and `import_export_value` in `import`. +/// Thus these must remain valid for the lifetime of `import`. +/// +/// The caller owns all data involved. +/// `import_export_value` will be written to based on `tag`. +wasmer_result_t wasmer_import_object_get_import(const wasmer_import_object_t *import_object, + wasmer_byte_array namespace_, + wasmer_byte_array name, + wasmer_import_t *import, + wasmer_import_export_value *import_export_value, + uint32_t tag); + +/// Frees the memory allocated in `wasmer_import_object_iter_next` +/// +/// This function does not free the memory in `wasmer_import_object_t`; +/// it only frees memory allocated while querying a `wasmer_import_object_t`. +void wasmer_import_object_imports_destroy(wasmer_import_t *imports, uint32_t imports_len); + +/// Returns true if further calls to `wasmer_import_object_iter_next` will +/// not return any new data +bool wasmer_import_object_iter_at_end(wasmer_import_object_iter_t *import_object_iter); + +/// Frees the memory allocated by `wasmer_import_object_iterate_functions` +void wasmer_import_object_iter_destroy(wasmer_import_object_iter_t *import_object_iter); + +/// Writes the next value to `import`. `WASMER_ERROR` is returned if there +/// was an error or there's nothing left to return. +/// +/// To free the memory allocated here, pass the import to `wasmer_import_object_imports_destroy`. +/// To check if the iterator is done, use `wasmer_import_object_iter_at_end`. +wasmer_result_t wasmer_import_object_iter_next(wasmer_import_object_iter_t *import_object_iter, + wasmer_import_t *import); + +/// Create an iterator over the functions in the import object. +/// Get the next import with `wasmer_import_object_iter_next` +/// Free the iterator with `wasmer_import_object_iter_destroy` +wasmer_import_object_iter_t *wasmer_import_object_iterate_functions(const wasmer_import_object_t *import_object); + /// Creates a new empty import object. /// See also `wasmer_import_object_append` wasmer_import_object_t *wasmer_import_object_new(); -/// Calls an instances exported function by `name` with the provided parameters. -/// Results are set using the provided `results` pointer. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. +/// Calls an exported function of a WebAssembly instance by `name` +/// with the provided parameters. The exported function results are +/// stored on the provided `results` pointer. +/// +/// This function returns `wasmer_result_t::WASMER_OK` upon success, +/// `wasmer_result_t::WASMER_ERROR` otherwise. You can use +/// `wasmer_last_error_message()` to get the generated error message. +/// +/// Potential errors are the following: +/// +/// * `instance` is a null pointer, +/// * `name` is a null pointer, +/// * `params` is a null pointer. +/// +/// Example of calling an exported function that needs two parameters, and returns one value: +/// +/// ```c +/// // First argument. +/// wasmer_value_t argument_one = { +/// .tag = WASM_I32, +/// .value.I32 = 3, +/// }; +/// +/// // Second argument. +/// wasmer_value_t argument_two = { +/// .tag = WASM_I32, +/// .value.I32 = 4, +/// }; +/// +/// // First result. +/// wasmer_value_t result_one; +/// +/// // All arguments and results. +/// wasmer_value_t arguments[] = {argument_one, argument_two}; +/// wasmer_value_t results[] = {result_one}; +/// +/// wasmer_result_t call_result = wasmer_instance_call( +/// instance, // instance pointer +/// "sum", // the exported function name +/// arguments, // the arguments +/// 2, // the number of arguments +/// results, // the results +/// 1 // the number of results +/// ); +/// +/// if (call_result == WASMER_OK) { +/// printf("Result is: %d\n", results[0].value.I32); +/// } +/// ``` wasmer_result_t wasmer_instance_call(wasmer_instance_t *instance, const char *name, const wasmer_value_t *params, @@ -346,89 +706,362 @@ wasmer_value_t *results, uint32_t results_len); -/// Gets the `data` field within the context. +/// Gets the data that can be hold by an instance. +/// +/// This function is complementary of +/// `wasmer_instance_context_data_set()`. Please read its +/// documentation. You can also read the documentation of +/// `wasmer_instance_context_t` to get other examples. +/// +/// This function returns nothing if `ctx` is a null pointer. void *wasmer_instance_context_data_get(const wasmer_instance_context_t *ctx); -/// Sets the `data` field of the instance context. This context will be -/// passed to all imported function for instance. -void wasmer_instance_context_data_set(wasmer_instance_t *instance, void *data_ptr); +/// Sets the data that can be hold by an instance context. +/// +/// An instance context (represented by the opaque +/// `wasmer_instance_context_t` structure) can hold user-defined +/// data. This function sets the data. This function is complementary +/// of `wasmer_instance_context_data_get()`. +/// +/// This function does nothing if `instance` is a null pointer. +/// +/// Example: +/// +/// ```c +/// // Define your own data. +/// typedef struct { +/// // … +/// } my_data; +/// +/// // Allocate them and set them on the given instance. +/// my_data *data = malloc(sizeof(my_data)); +/// data->… = …; +/// wasmer_instance_context_data_set(instance, (void*) data); +/// +/// // You can read your data. +/// { +/// my_data *data = (my_data*) wasmer_instance_context_data_get(wasmer_instance_context_get(instance)); +/// // … +/// } +/// ``` +void wasmer_instance_context_data_set(wasmer_instance_t *instance, + void *data_ptr); -/// Extracts the instance's context and returns it. +/// Returns the instance context. Learn more by looking at the +/// `wasmer_instance_context_t` struct. +/// +/// This function returns `null` if `instance` is a null pointer. +/// +/// Example: +/// +/// ```c +/// const wasmer_instance_context_get *context = wasmer_instance_context_get(instance); +/// my_data *data = (my_data *) wasmer_instance_context_data_get(context); +/// // Do something with `my_data`. +/// ``` +/// +/// It is often useful with `wasmer_instance_context_data_set()`. const wasmer_instance_context_t *wasmer_instance_context_get(wasmer_instance_t *instance); -/// Gets the memory within the context at the index `memory_idx`. -/// The index is always 0 until multiple memories are supported. +/// Gets the `memory_idx`th memory of the instance. +/// +/// Note that the index is always `0` until multiple memories are supported. +/// +/// This function is mostly used inside host functions (aka imported +/// functions) to read the instance memory. +/// +/// Example of a _host function_ that reads and prints a string based on a pointer and a length: +/// +/// ```c +/// void print_string(const wasmer_instance_context_t *context, int32_t pointer, int32_t length) { +/// // Get the 0th memory. +/// const wasmer_memory_t *memory = wasmer_instance_context_memory(context, 0); +/// +/// // Get the memory data as a pointer. +/// uint8_t *memory_bytes = wasmer_memory_data(memory); +/// +/// // Print what we assumed to be a string! +/// printf("%.*s", length, memory_bytes + pointer); +/// } +/// ``` const wasmer_memory_t *wasmer_instance_context_memory(const wasmer_instance_context_t *ctx, uint32_t _memory_idx); -/// Frees memory for the given Instance +/// Frees memory for the given `wasmer_instance_t`. +/// +/// Check the `wasmer_instantiate()` function to get a complete +/// example. +/// +/// If `instance` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get an instance. +/// wasmer_instance_t *instance = NULL; +/// wasmer_instantiate(&instance, bytes, bytes_length, imports, 0); +/// +/// // Destroy the instance. +/// wasmer_instance_destroy(instance); +/// ``` void wasmer_instance_destroy(wasmer_instance_t *instance); -/// Gets Exports for the given instance -/// The caller owns the object and should call `wasmer_exports_destroy` to free it. +/// Gets all the exports of the given WebAssembly instance. +/// +/// This function stores a Rust vector of exports into `exports` as an +/// opaque pointer of kind `wasmer_exports_t`. +/// +/// As is, you can do anything with `exports` except using the +/// companion functions, like `wasmer_exports_len()`, +/// `wasmer_exports_get()` or `wasmer_export_kind()`. See the example below. +/// +/// **Warning**: The caller owns the object and should call +/// `wasmer_exports_destroy()` to free it. +/// +/// Example: +/// +/// ```c +/// // Get the exports. +/// wasmer_exports_t *exports = NULL; +/// wasmer_instance_exports(instance, &exports); +/// +/// // Get the number of exports. +/// int exports_length = wasmer_exports_len(exports); +/// printf("Number of exports: %d\n", exports_length); +/// +/// // Read the first export. +/// wasmer_export_t *export = wasmer_exports_get(exports, 0); +/// +/// // Get the kind of the export. +/// wasmer_import_export_kind export_kind = wasmer_export_kind(export); +/// +/// // Assert it is a function (why not). +/// assert(export_kind == WASM_FUNCTION); +/// +/// // Read the export name. +/// wasmer_byte_array name_bytes = wasmer_export_name(export); +/// +/// assert(name_bytes.bytes_len == sizeof("sum") - 1); +/// assert(memcmp(name_bytes.bytes, "sum", sizeof("sum") - 1) == 0); +/// +/// // Destroy the exports. +/// wasmer_exports_destroy(exports); +/// ``` void wasmer_instance_exports(wasmer_instance_t *instance, wasmer_exports_t **exports); -/// Creates a new Instance from the given wasm bytes and imports. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. +/// Creates a new WebAssembly instance from the given bytes and imports. +/// +/// The result is stored in the first argument `instance` if +/// successful, i.e. when the function returns +/// `wasmer_result_t::WASMER_OK`. Otherwise +/// `wasmer_result_t::WASMER_ERROR` is returned, and +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` must +/// be used to read the error message. +/// +/// The caller is responsible to free the instance with +/// `wasmer_instance_destroy()`. +/// +/// Example: +/// +/// ```c +/// // 1. Read a WebAssembly module from a file. +/// FILE *file = fopen("sum.wasm", "r"); +/// fseek(file, 0, SEEK_END); +/// long bytes_length = ftell(file); +/// uint8_t *bytes = malloc(bytes_length); +/// fseek(file, 0, SEEK_SET); +/// fread(bytes, 1, bytes_length, file); +/// fclose(file); +/// +/// // 2. Declare the imports (here, none). +/// wasmer_import_t imports[] = {}; +/// +/// // 3. Instantiate the WebAssembly module. +/// wasmer_instance_t *instance = NULL; +/// wasmer_result_t result = wasmer_instantiate(&instance, bytes, bytes_length, imports, 0); +/// +/// // 4. Check for errors. +/// if (result != WASMER_OK) { +/// int error_length = wasmer_last_error_length(); +/// char *error = malloc(error_length); +/// wasmer_last_error_message(error, error_length); +/// // Do something with `error`… +/// } +/// +/// // 5. Free the memory! +/// wasmer_instance_destroy(instance); +/// ``` wasmer_result_t wasmer_instantiate(wasmer_instance_t **instance, uint8_t *wasm_bytes, uint32_t wasm_bytes_len, wasmer_import_t *imports, int imports_len); -/// Gets the length in bytes of the last error. +/// Gets the length in bytes of the last error if any. +/// /// This can be used to dynamically allocate a buffer with the correct number of /// bytes needed to store a message. -/// # Example -/// ```c -/// int error_len = wasmer_last_error_length(); -/// char *error_str = malloc(error_len); -/// ``` +/// +/// See `wasmer_last_error_message()` to get a full example. int wasmer_last_error_length(); -/// Stores the last error message into the provided buffer up to the given `length`. -/// The `length` parameter must be large enough to store the last error message. -/// Returns the length of the string in bytes. -/// Returns `-1` if an error occurs. -/// # Example +/// Gets the last error message if any into the provided buffer +/// `buffer` up to the given `length`. +/// +/// The `length` parameter must be large enough to store the last +/// error message. Ideally, the value should come from +/// `wasmer_last_error_length()`. +/// +/// The function returns the length of the string in bytes, `-1` if an +/// error occurs. Potential errors are: +/// +/// * The buffer is a null pointer, +/// * The buffer is too smal to hold the error message. +/// +/// Note: The error message always has a trailing null character. +/// +/// Example: +/// /// ```c -/// int error_len = wasmer_last_error_length(); -/// char *error_str = malloc(error_len); -/// wasmer_last_error_message(error_str, error_len); -/// printf("Error str: `%s`\n", error_str); +/// int error_length = wasmer_last_error_length(); +/// +/// if (error_length > 0) { +/// char *error_message = malloc(error_length); +/// wasmer_last_error_message(error_message, error_length); +/// printf("Error message: `%s`\n", error_message); +/// } else { +/// printf("No error message\n"); +/// } /// ``` int wasmer_last_error_message(char *buffer, int length); -/// Gets the start pointer to the bytes within a Memory -uint8_t *wasmer_memory_data(const wasmer_memory_t *mem); +/// Gets a pointer to the beginning of the contiguous memory data +/// bytes. +/// +/// The function returns `NULL` if `memory` is a null pointer. +/// +/// Note that when the memory grows, it can be reallocated, and thus +/// the returned pointer can be invalidated. +/// +/// Example: +/// +/// ```c +/// uint8_t *memory_data = wasmer_memory_data(memory); +/// char *str = (char*) malloc(sizeof(char) * 7); +/// +/// for (uint32_t nth = 0; nth < 7; ++nth) { +/// str[nth] = (char) memory_data[nth]; +/// } +/// ``` +uint8_t *wasmer_memory_data(const wasmer_memory_t *memory); -/// Gets the size in bytes of a Memory -uint32_t wasmer_memory_data_length(wasmer_memory_t *mem); +/// Gets the size in bytes of the memory data. +/// +/// This function returns 0 if `memory` is a null pointer. +/// +/// Example: +/// +/// ```c +/// uint32_t memory_data_length = wasmer_memory_data_length(memory); +/// ``` +uint32_t wasmer_memory_data_length(const wasmer_memory_t *memory); -/// Frees memory for the given Memory +/// Frees memory for the given `wasmer_memory_t`. +/// +/// Check the `wasmer_memory_new()` function to get a complete +/// example. +/// +/// If `memory` is a null pointer, this function does nothing. +/// +/// Example: +/// +/// ```c +/// // Get a memory. +/// wasmer_memory_t *memory = NULL; +/// wasmer_result_t result = wasmer_memory_new(&memory, memory_descriptor); +/// +/// // Destroy the memory. +/// wasmer_memory_destroy(memory); +/// ``` void wasmer_memory_destroy(wasmer_memory_t *memory); -/// Grows a Memory by the given number of pages. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. +/// Grows a memory by the given number of pages (of 65Kb each). +/// +/// The functions return `wasmer_result_t::WASMER_OK` upon success, +/// `wasmer_result_t::WASMER_ERROR` otherwise. Use +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` to +/// read the error message. +/// +/// Example: +/// +/// ```c +/// wasmer_result_t result = wasmer_memory_grow(memory, 10); +/// +/// if (result != WASMER_OK) { +/// // … +/// } +/// ``` wasmer_result_t wasmer_memory_grow(wasmer_memory_t *memory, uint32_t delta); -/// Returns the current length in pages of the given memory +/// Reads the current length (in pages) of the given memory. +/// +/// The function returns zero if `memory` is a null pointer. +/// +/// Example: +/// +/// ```c +/// uint32_t memory_length = wasmer_memory_length(memory); +/// +/// printf("Memory pages length: %d\n", memory_length); +/// ``` uint32_t wasmer_memory_length(const wasmer_memory_t *memory); -/// Creates a new Memory for the given descriptor and initializes the given -/// pointer to pointer to a pointer to the new memory. -/// The caller owns the object and should call `wasmer_memory_destroy` to free it. -/// Returns `wasmer_result_t::WASMER_OK` upon success. -/// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` -/// and `wasmer_last_error_message` to get an error message. +/// Creates a new empty WebAssembly memory for the given descriptor. +/// +/// The result is stored in the first argument `memory` if successful, +/// i.e. when the function returns +/// `wasmer_result_t::WASMER_OK`. Otherwise, +/// `wasmer_result_t::WASMER_ERROR` is returned, and +/// `wasmer_last_error_length()` with `wasmer_last_error_message()` +/// must be used to read the error message. +/// +/// The caller owns the memory and is responsible to free it with +/// `wasmer_memory_destroy()`. +/// +/// Example: +/// +/// ```c +/// // 1. The memory object. +/// wasmer_memory_t *memory = NULL; +/// +/// // 2. The memory descriptor. +/// wasmer_limits_t memory_descriptor = { +/// .min = 10, +/// .max = { +/// .has_some = true, +/// .some = 15, +/// }, +/// }; +/// +/// // 3. Initialize the memory. +/// wasmer_result_t result = wasmer_memory_new(&memory, memory_descriptor); +/// +/// if (result != WASMER_OK) { +/// int error_length = wasmer_last_error_length(); +/// char *error = malloc(error_length); +/// wasmer_last_error_message(error, error_length); +/// // Do something with `error`… +/// } +/// +/// // 4. Free the memory! +/// wasmer_memory_destroy(memory); +/// ``` wasmer_result_t wasmer_memory_new(wasmer_memory_t **memory, wasmer_limits_t limits); /// Deserialize the given serialized module. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_module_deserialize(wasmer_module_t **module, @@ -438,15 +1071,18 @@ void wasmer_module_destroy(wasmer_module_t *module); /// Given: -/// A prepared `wasmer` import-object -/// A compiled wasmer module +/// * A prepared `wasmer` import-object +/// * A compiled wasmer module +/// /// Instantiates a wasmer instance wasmer_result_t wasmer_module_import_instantiate(wasmer_instance_t **instance, const wasmer_module_t *module, const wasmer_import_object_t *import_object); /// Creates a new Instance from the given module and imports. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_module_instantiate(const wasmer_module_t *module, @@ -455,8 +1091,11 @@ int imports_len); /// Serialize the given Module. +/// /// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_module_serialize(wasmer_serialized_module_t **serialized_module, @@ -469,8 +1108,11 @@ void wasmer_serialized_module_destroy(wasmer_serialized_module_t *serialized_module); /// Transform a sequence of bytes into a serialized module. +/// /// The caller owns the object and should call `wasmer_serialized_module_destroy` to free it. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_serialized_module_from_bytes(wasmer_serialized_module_t **serialized_module, @@ -481,7 +1123,9 @@ void wasmer_table_destroy(wasmer_table_t *table); /// Grows a Table by the given number of elements. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_table_grow(wasmer_table_t *table, uint32_t delta); @@ -491,42 +1135,139 @@ /// Creates a new Table for the given descriptor and initializes the given /// pointer to pointer to a pointer to the new Table. +/// /// The caller owns the object and should call `wasmer_table_destroy` to free it. +/// /// Returns `wasmer_result_t::WASMER_OK` upon success. +/// /// Returns `wasmer_result_t::WASMER_ERROR` upon failure. Use `wasmer_last_error_length` /// and `wasmer_last_error_message` to get an error message. wasmer_result_t wasmer_table_new(wasmer_table_t **table, wasmer_limits_t limits); +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Adds a callinfo trampoline to the builder. +/// +/// Deprecated. In a future version `DynamicFunc::new` will be exposed to the C API and should be used instead of this function. uintptr_t wasmer_trampoline_buffer_builder_add_callinfo_trampoline(wasmer_trampoline_buffer_builder_t *builder, const wasmer_trampoline_callable_t *func, const void *ctx, uint32_t num_params); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Adds a context trampoline to the builder. uintptr_t wasmer_trampoline_buffer_builder_add_context_trampoline(wasmer_trampoline_buffer_builder_t *builder, const wasmer_trampoline_callable_t *func, const void *ctx); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Finalizes the trampoline builder into an executable buffer. wasmer_trampoline_buffer_t *wasmer_trampoline_buffer_builder_build(wasmer_trampoline_buffer_builder_t *builder); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Creates a new trampoline builder. wasmer_trampoline_buffer_builder_t *wasmer_trampoline_buffer_builder_new(); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Destroys the trampoline buffer if not null. void wasmer_trampoline_buffer_destroy(wasmer_trampoline_buffer_t *buffer); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Returns the callable pointer for the trampoline with index `idx`. const wasmer_trampoline_callable_t *wasmer_trampoline_buffer_get_trampoline(const wasmer_trampoline_buffer_t *buffer, uintptr_t idx); +#endif +#if (!defined(_WIN32) && defined(ARCH_X86_64)) /// Returns the context added by `add_context_trampoline`, from within the callee function. void *wasmer_trampoline_get_context(); +#endif -/// Returns true for valid wasm bytes and false for invalid bytes +/// Stop the execution of a host function, aka imported function. The +/// function must be used _only_ inside a host function. +/// +/// The pointer to `wasmer_instance_context_t` is received by the host +/// function as its first argument. Just passing it to `ctx` is fine. +/// +/// The error message must have a greater lifetime than the host +/// function itself since the error is read outside the host function +/// with `wasmer_last_error_message`. +/// +/// This function returns `wasmer_result_t::WASMER_ERROR` if `ctx` or +/// `error_message` are null. +/// +/// This function never returns otherwise. +wasmer_result_t wasmer_trap(const wasmer_instance_context_t *ctx, const char *error_message); + +/// Validates a sequence of bytes hoping it represents a valid WebAssembly module. +/// +/// The function returns true if the bytes are valid, false otherwise. +/// +/// Example: +/// +/// ```c +/// bool result = wasmer_validate(bytes, bytes_length); +/// +/// if (false == result) { +/// // Do something… +/// } +/// ``` bool wasmer_validate(const uint8_t *wasm_bytes, uint32_t wasm_bytes_len); +#if defined(WASMER_WASI_ENABLED) +/// Convenience function that creates a WASI import object with no arguments, +/// environment variables, preopened files, or mapped directories. +/// +/// This function is the same as calling [`wasmer_wasi_generate_import_object`] with all +/// empty values. +wasmer_import_object_t *wasmer_wasi_generate_default_import_object(); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Creates a WASI import object. +/// +/// This function treats null pointers as empty collections. +/// For example, passing null for a string in `args`, will lead to a zero +/// length argument in that position. +wasmer_import_object_t *wasmer_wasi_generate_import_object(const wasmer_byte_array *args, + unsigned int args_len, + const wasmer_byte_array *envs, + unsigned int envs_len, + const wasmer_byte_array *preopened_files, + unsigned int preopened_files_len, + const wasmer_wasi_map_dir_entry_t *mapped_dirs, + unsigned int mapped_dirs_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Creates a WASI import object for a specific version. +/// +/// This function is similar to `wasmer_wasi_generate_import_object` +/// except that the first argument describes the WASI version. +/// +/// The version is expected to be of kind `Version`. +wasmer_import_object_t *wasmer_wasi_generate_import_object_for_version(unsigned char version, + const wasmer_byte_array *args, + unsigned int args_len, + const wasmer_byte_array *envs, + unsigned int envs_len, + const wasmer_byte_array *preopened_files, + unsigned int preopened_files_len, + const wasmer_wasi_map_dir_entry_t *mapped_dirs, + unsigned int mapped_dirs_len); +#endif + +#if defined(WASMER_WASI_ENABLED) +/// Find the version of WASI used by the module. +/// +/// In case of error, the returned version is `Version::Unknown`. +Version wasmer_wasi_get_version(const wasmer_module_t *module); +#endif + } // extern "C" #endif // WASMER_H
diff --git a/tools/VERSION b/tools/VERSION index 2753997..2fcf00b 100644 --- a/tools/VERSION +++ b/tools/VERSION
@@ -27,5 +27,5 @@ MAJOR 2 MINOR 10 PATCH 0 -PRERELEASE 13 +PRERELEASE 14 PRERELEASE_PATCH 0 \ No newline at end of file