diff --git a/.gitignore b/.gitignore
index 541b49d1..9c07c6b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,7 +81,7 @@ build.xcarchive
## Obj-C/Swift specific
*.hmap
*.ipa
-
+/sdks/swift/Mentat/External-Dependencies
# Android & IntelliJ
**/*.iml
diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs
index a665b25a..b08d7d38 100644
--- a/ffi/src/lib.rs
+++ b/ffi/src/lib.rs
@@ -62,10 +62,12 @@
//! wrapped inside a Rust closure and added to a [TxObserver](mentat::TxObserver) struct. This is then used to
//! register the observer with the store.
//!
-//! [Result](std::result::Result) and [Option](std::option::Option) Rust types have `repr(C)` structs that mirror them. This is to provide a more
-//! native access pattern to callers and to enable easier passing of optional types and error
-//! propogation. These types have implemented [From](std::convert::From) such that conversion from the Rust type
-//! to the C type is as painless as possible.
+//! Functions that may fail take an out parameter of type `*mut ExternError`. In the event the
+//! function fails, information about the error that occured will be stored inside it (and,
+//! typically, a null pointer will be returned). Convenience functions for unpacking a
+//! `Result` as a `*mut T` while writing any error to the `ExternError` are provided as
+//! `translate_result`, `translate_opt_result` (for `Result
@@ -77,10 +75,10 @@ import java.io.IOException;
* inProgress.commit();
* }
*/
-public class InProgress extends RustObject {
+public class InProgress extends RustObject {
- public InProgress(Pointer pointer) {
- this.rawPointer = pointer;
+ public InProgress(JNA.InProgress pointer) {
+ super(pointer);
}
/**
@@ -89,10 +87,7 @@ public class InProgress extends RustObject {
* @return an {@link InProgressBuilder} for this {@link InProgress}
*/
public InProgressBuilder builder() {
- this.validate();
- InProgressBuilder builder = new InProgressBuilder(JNA.INSTANCE.in_progress_builder(this.rawPointer));
- this.rawPointer = null;
- return builder;
+ return new InProgressBuilder(JNA.INSTANCE.in_progress_builder(this.consumePointer()));
}
/**
@@ -102,11 +97,8 @@ public class InProgress extends RustObject {
* @param entid The `Entid` for this entity.
* @return an `EntityBuilder` for this `InProgress`
*/
- public EntityBuilder builderForEntid(long entid){
- this.validate();
- EntityBuilder builder = new EntityBuilder(JNA.INSTANCE.in_progress_entity_builder_from_entid(this.rawPointer, entid));
- this.rawPointer = null;
- return builder;
+ public EntityBuilder builderForEntid(long entid) {
+ return new EntityBuilder(JNA.INSTANCE.in_progress_entity_builder_from_entid(this.consumePointer(), entid));
}
/**
@@ -117,10 +109,7 @@ public class InProgress extends RustObject {
* @return an `EntityBuilder` for this `InProgress`
*/
public EntityBuilder builderForTempid(String tempid){
- this.validate();
- EntityBuilder builder = new EntityBuilder(JNA.INSTANCE.in_progress_entity_builder_from_temp_id(this.rawPointer, tempid));
- this.rawPointer = null;
- return builder;
+ return new EntityBuilder(JNA.INSTANCE.in_progress_entity_builder_from_temp_id(this.consumePointer(), tempid));
}
/**
@@ -146,13 +135,13 @@ public class InProgress extends RustObject {
* @return The `TxReport` generated by the transact.
*/
public TxReport transact(String transaction) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_transact(this.rawPointer, transaction);
- if (result.isFailure()) {
- Log.e("InProgress", result.err);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.TxReport txr = JNA.INSTANCE.in_progress_transact(this.validPointer(), transaction, err);
+ if (err.isFailure()) {
+ Log.e("InProgress", err.consumeErrorMessage());
return null;
}
- return new TxReport(result.ok);
+ return new TxReport(txr);
}
/**
@@ -163,12 +152,9 @@ public class InProgress extends RustObject {
* TODO throw exception if error occurs
*/
public void commit() {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_commit(this.rawPointer);
- this.rawPointer = null;
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_commit(this.consumePointer(), err);
+ err.logAndConsumeError("InProgress");
}
/**
@@ -178,18 +164,13 @@ public class InProgress extends RustObject {
* TODO throw exception if error occurs
*/
public void rollback() {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_rollback(this.rawPointer);
- this.rawPointer = null;
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_rollback(this.consumePointer(), err);
+ err.logAndConsumeError("InProgress");
}
@Override
- public void close() throws IOException {
- if (this.rawPointer != null) {
- JNA.INSTANCE.in_progress_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.InProgress p) {
+ JNA.INSTANCE.in_progress_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressBuilder.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressBuilder.java
index f23effe0..4aaba924 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressBuilder.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressBuilder.java
@@ -14,7 +14,6 @@ import android.util.Log;
import com.sun.jna.Pointer;
-import java.io.IOException;
import java.util.Date;
import java.util.UUID;
@@ -56,10 +55,10 @@ import java.util.UUID;
* builder.commit();
* }
*/
-public class InProgressBuilder extends RustObject {
+public class InProgressBuilder extends RustObject {
- public InProgressBuilder(Pointer pointer) {
- this.rawPointer = pointer;
+ public InProgressBuilder(JNA.InProgressBuilder pointer) {
+ super(pointer);
}
/**
* Asserts the value of attribute `keyword` to be the provided `value`.
@@ -71,11 +70,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, long value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_long(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_long(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -87,11 +84,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void addRef(long entid, String keyword, long value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_ref(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_ref(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -103,11 +98,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void addKeyword(long entid, String keyword, String value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_keyword(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_keyword(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -119,11 +112,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, boolean value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_boolean(this.rawPointer, entid, keyword, value ? 1 : 0);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_boolean(this.validPointer(), entid, keyword, value ? 1 : 0, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -135,11 +126,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, double value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_double(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_double(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -151,11 +140,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, Date value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_timestamp(this.rawPointer, entid, keyword, value.getTime() * 1_000);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_timestamp(this.validPointer(), entid, keyword, value.getTime() * 1_000, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -167,11 +154,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, String value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_add_string(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_string(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -183,12 +168,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be asserted
*/
public void add(long entid, String keyword, UUID value) {
- this.validate();
-
- RustResult result = JNA.INSTANCE.in_progress_builder_add_uuid(this.rawPointer, entid, keyword, getPointerForUUID(value));
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_add_uuid(this.validPointer(), entid, keyword, getPointerForUUID(value), error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -201,11 +183,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, long value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_long(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_long(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
@@ -219,11 +199,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retractRef(long entid, String keyword, long value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_ref(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_ref(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -236,11 +214,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retractKeyword(long entid, String keyword, String value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_keyword(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_keyword(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -253,11 +229,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, boolean value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_boolean(this.rawPointer, entid, keyword, value ? 1 : 0);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_boolean(this.validPointer(), entid, keyword, value ? 1 : 0, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -270,11 +244,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, double value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_double(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_double(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -287,11 +259,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, Date value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_timestamp(this.rawPointer, entid, keyword, value.getTime() * 1_000);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_timestamp(this.validPointer(), entid, keyword, value.getTime() * 1_000, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -304,11 +274,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, String value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_string(this.rawPointer, entid, keyword, value);
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_string(this.validPointer(), entid, keyword, value, error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -321,11 +289,9 @@ public class InProgressBuilder extends RustObject {
* @param value The value to be retracted
*/
public void retract(long entid, String keyword, UUID value) {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_retract_uuid(this.rawPointer, entid, keyword, this.getPointerForUUID(value));
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
- }
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.INSTANCE.in_progress_builder_retract_uuid(this.validPointer(), entid, keyword, this.getPointerForUUID(value), error);
+ error.logAndConsumeError("InProgressBuilder");
}
/**
@@ -343,9 +309,7 @@ public class InProgressBuilder extends RustObject {
* the {@link TxReport} generated by the transact.
*/
public InProgressTransactionResult transact() {
- this.validate();
- InProgressTransactionResult result = JNA.INSTANCE.in_progress_builder_transact(this.rawPointer);
- this.rawPointer = null;
+ InProgressTransactionResult result = JNA.INSTANCE.in_progress_builder_transact(this.consumePointer());
return result;
}
@@ -362,21 +326,17 @@ public class InProgressBuilder extends RustObject {
* @return The {@link TxReport} generated by the commit.
*/
public TxReport commit() {
- this.validate();
- RustResult result = JNA.INSTANCE.in_progress_builder_commit(this.rawPointer);
- this.rawPointer = null;
- if (result.isFailure()) {
- Log.e("InProgressBuilder", result.err);
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.TxReport result = JNA.INSTANCE.in_progress_builder_commit(this.consumePointer(), error);
+ if (error.isFailure()) {
+ Log.e("InProgressBuilder", error.consumeErrorMessage());
return null;
}
-
- return new TxReport(result.ok);
+ return new TxReport(result);
}
@Override
- public void close() throws IOException {
- if (this.rawPointer != null) {
- JNA.INSTANCE.in_progress_builder_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.InProgressBuilder p) {
+ JNA.INSTANCE.in_progress_builder_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressTransactionResult.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressTransactionResult.java
index 6148d16e..a58bda5e 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressTransactionResult.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/InProgressTransactionResult.java
@@ -15,43 +15,57 @@ import android.util.Log;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
-import java.io.Closeable;
-import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-public class InProgressTransactionResult extends Structure implements Closeable {
+public class InProgressTransactionResult extends Structure {
public static class ByReference extends InProgressTransactionResult implements Structure.ByReference {
}
public static class ByValue extends InProgressTransactionResult implements Structure.ByValue {
}
- public Pointer inProgress;
- public RustResult.ByReference result;
+ public JNA.InProgress inProgress;
+ public JNA.TxReport txReport;
+ public RustError error;
@Override
protected List getFieldOrder() {
- return Arrays.asList("inProgress", "result");
+ return Arrays.asList("inProgress", "txReport", "error");
}
public InProgress getInProgress() {
- return new InProgress(this.inProgress);
+ if (this.inProgress == null) {
+ throw new NullPointerException("Already consumed InProgress");
+ }
+ InProgress ip = new InProgress(this.inProgress);
+ this.inProgress = null;
+ return ip;
+
}
-
+
public TxReport getReport() {
- if (this.result.isFailure()) {
- Log.e("InProgressTransactRes", this.result.err);
+ if (this.error.isFailure()) {
+ Log.e("InProgressTransactRes", this.error.consumeErrorMessage());
return null;
}
-
- return new TxReport(this.result.ok);
+ if (this.txReport == null) {
+ throw new NullPointerException("Already consumed TxReport");
+ }
+ JNA.TxReport report = this.txReport;
+ this.txReport = null;
+ return new TxReport(report);
}
@Override
- public void close() throws IOException {
- if (this.getPointer() != null) {
- JNA.INSTANCE.destroy(this.getPointer());
+ protected void finalize() {
+ if (this.txReport != null) {
+ JNA.INSTANCE.tx_report_destroy(this.txReport);
+ this.txReport = null;
+ }
+ if (this.inProgress != null) {
+ JNA.INSTANCE.in_progress_destroy(this.inProgress);
+ this.inProgress = null;
}
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java
index 1b3b0023..b8ba5d42 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/JNA.java
@@ -14,6 +14,9 @@ import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
+import com.sun.jna.PointerType;
+
+import java.lang.reflect.Type;
/**
* JNA interface for FFI to Mentat's Rust library
@@ -26,136 +29,148 @@ public interface JNA extends Library {
JNA INSTANCE = (JNA) Native.loadLibrary(JNA_LIBRARY_NAME, JNA.class);
- Pointer store_open(String dbPath);
+
+ class Store extends PointerType {}
+ class QueryBuilder extends PointerType {}
+ class TypedValue extends PointerType {}
+ class TypedValueList extends PointerType {}
+ class TypedValueListIter extends PointerType {}
+ class RelResult extends PointerType {}
+ class RelResultIter extends PointerType {}
+ class TxReport extends PointerType {}
+ class InProgress extends PointerType {}
+ class InProgressBuilder extends PointerType {}
+ class EntityBuilder extends PointerType {}
+
+ Store store_open(String dbPath);
void destroy(Pointer obj);
- void query_builder_destroy(Pointer obj);
- void store_destroy(Pointer obj);
- void typed_value_destroy(Pointer obj);
- void typed_value_list_destroy(Pointer obj);
- void typed_value_list_iter_destroy(Pointer obj);
- void typed_value_result_set_destroy(Pointer obj);
- void typed_value_result_set_iter_destroy(Pointer obj);
- void tx_report_destroy(Pointer obj);
- void in_progress_destroy(Pointer obj);
- void in_progress_builder_destroy(Pointer obj);
- void entity_builder_destroy(Pointer obj);
+ void uuid_destroy(Pointer obj);
+ void query_builder_destroy(QueryBuilder obj);
+ void store_destroy(Store obj);
+ void typed_value_destroy(TypedValue obj);
+ void typed_value_list_destroy(TypedValueList obj);
+ void typed_value_list_iter_destroy(TypedValueListIter obj);
+ void typed_value_result_set_destroy(RelResult obj);
+ void typed_value_result_set_iter_destroy(RelResultIter obj);
+ void tx_report_destroy(TxReport obj);
+ void in_progress_destroy(InProgress obj);
+ void in_progress_builder_destroy(InProgressBuilder obj);
+ void entity_builder_destroy(EntityBuilder obj);
+ void rust_c_string_destroy(Pointer str);
// caching
- RustResult store_cache_attribute_forward(Pointer store, String attribute);
- RustResult store_cache_attribute_reverse(Pointer store, String attribute);
- RustResult store_cache_attribute_bi_directional(Pointer store, String attribute);
+ void store_cache_attribute_forward(Store store, String attribute, RustError.ByReference err);
+ void store_cache_attribute_reverse(Store store, String attribute, RustError.ByReference err);
+ void store_cache_attribute_bi_directional(Store store, String attribute, RustError.ByReference err);
// transact
- RustResult store_transact(Pointer store, String transaction);
- Pointer tx_report_entity_for_temp_id(Pointer report, String tempid);
- long tx_report_get_entid(Pointer report);
- long tx_report_get_tx_instant(Pointer report);
- RustResult store_begin_transaction(Pointer store);
+ TxReport store_transact(Store store, String transaction, RustError.ByReference err);
+ Pointer tx_report_entity_for_temp_id(TxReport report, String tempid); // returns a pointer to a 64 bit int on the heap
+ long tx_report_get_entid(TxReport report);
+ long tx_report_get_tx_instant(TxReport report);
+ InProgress store_begin_transaction(Store store, RustError.ByReference error);
// in progress
- RustResult in_progress_transact(Pointer in_progress, String transaction);
- RustResult in_progress_commit(Pointer in_progress);
- RustResult in_progress_rollback(Pointer in_progress);
- Pointer in_progress_builder(Pointer in_progress);
- Pointer in_progress_entity_builder_from_temp_id(Pointer in_progress, String temp_id);
- Pointer in_progress_entity_builder_from_entid(Pointer in_progress, long entid);
+ TxReport in_progress_transact(InProgress in_progress, String transaction, RustError.ByReference err);
+ void in_progress_commit(InProgress in_progress, RustError.ByReference err);
+ void in_progress_rollback(InProgress in_progress, RustError.ByReference err);
+ InProgressBuilder in_progress_builder(InProgress in_progress);
+ EntityBuilder in_progress_entity_builder_from_temp_id(InProgress in_progress, String temp_id);
+ EntityBuilder in_progress_entity_builder_from_entid(InProgress in_progress, long entid);
// in_progress entity building
- RustResult store_in_progress_builder(Pointer store);
- RustResult in_progress_builder_add_string(Pointer builder, long entid, String kw, String value);
- RustResult in_progress_builder_add_long(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_add_ref(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_add_keyword(Pointer builder, long entid, String kw, String value);
- RustResult in_progress_builder_add_timestamp(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_add_boolean(Pointer builder, long entid, String kw, int value);
- RustResult in_progress_builder_add_double(Pointer builder, long entid, String kw, double value);
- RustResult in_progress_builder_add_uuid(Pointer builder, long entid, String kw, Pointer value);
- RustResult in_progress_builder_retract_string(Pointer builder, long entid, String kw, String value);
- RustResult in_progress_builder_retract_long(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_retract_ref(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_retract_keyword(Pointer builder, long entid, String kw, String value);
- RustResult in_progress_builder_retract_timestamp(Pointer builder, long entid, String kw, long value);
- RustResult in_progress_builder_retract_boolean(Pointer builder, long entid, String kw, int value);
- RustResult in_progress_builder_retract_double(Pointer builder, long entid, String kw, double value);
- RustResult in_progress_builder_retract_uuid(Pointer builder, long entid, String kw, Pointer value);
- InProgressTransactionResult in_progress_builder_transact(Pointer builder);
- RustResult in_progress_builder_commit(Pointer builder);
+ InProgressBuilder store_in_progress_builder(Store store, RustError.ByReference err);
+ void in_progress_builder_add_string(InProgressBuilder builder, long entid, String kw, String value, RustError.ByReference err);
+ void in_progress_builder_add_long(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_add_ref(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_add_keyword(InProgressBuilder builder, long entid, String kw, String value, RustError.ByReference err);
+ void in_progress_builder_add_timestamp(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_add_boolean(InProgressBuilder builder, long entid, String kw, int value, RustError.ByReference err);
+ void in_progress_builder_add_double(InProgressBuilder builder, long entid, String kw, double value, RustError.ByReference err);
+ void in_progress_builder_add_uuid(InProgressBuilder builder, long entid, String kw, Pointer value, RustError.ByReference err);
+ void in_progress_builder_retract_string(InProgressBuilder builder, long entid, String kw, String value, RustError.ByReference err);
+ void in_progress_builder_retract_long(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_retract_ref(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_retract_keyword(InProgressBuilder builder, long entid, String kw, String value, RustError.ByReference err);
+ void in_progress_builder_retract_timestamp(InProgressBuilder builder, long entid, String kw, long value, RustError.ByReference err);
+ void in_progress_builder_retract_boolean(InProgressBuilder builder, long entid, String kw, int value, RustError.ByReference err);
+ void in_progress_builder_retract_double(InProgressBuilder builder, long entid, String kw, double value, RustError.ByReference err);
+ void in_progress_builder_retract_uuid(InProgressBuilder builder, long entid, String kw, Pointer value, RustError.ByReference err);
+ InProgressTransactionResult.ByValue in_progress_builder_transact(InProgressBuilder builder);
+ TxReport in_progress_builder_commit(InProgressBuilder builder, RustError.ByReference err);
// entity building
- RustResult store_entity_builder_from_temp_id(Pointer store, String temp_id);
- RustResult store_entity_builder_from_entid(Pointer store, long entid);
- RustResult entity_builder_add_string(Pointer builder, String kw, String value);
- RustResult entity_builder_add_long(Pointer builder, String kw, long value);
- RustResult entity_builder_add_ref(Pointer builder, String kw, long value);
- RustResult entity_builder_add_keyword(Pointer builder, String kw, String value);
- RustResult entity_builder_add_boolean(Pointer builder, String kw, int value);
- RustResult entity_builder_add_double(Pointer builder, String kw, double value);
- RustResult entity_builder_add_timestamp(Pointer builder, String kw, long value);
- RustResult entity_builder_add_uuid(Pointer builder, String kw, Pointer value);
- RustResult entity_builder_retract_string(Pointer builder, String kw, String value);
- RustResult entity_builder_retract_long(Pointer builder, String kw, long value);
- RustResult entity_builder_retract_ref(Pointer builder, String kw, long value);
- RustResult entity_builder_retract_keyword(Pointer builder, String kw, String value);
- RustResult entity_builder_retract_boolean(Pointer builder, String kw, int value);
- RustResult entity_builder_retract_double(Pointer builder, String kw, double value);
- RustResult entity_builder_retract_timestamp(Pointer builder, String kw, long value);
- RustResult entity_builder_retract_uuid(Pointer builder, String kw, Pointer value);
- InProgressTransactionResult entity_builder_transact(Pointer builder);
- RustResult entity_builder_commit(Pointer builder);
-
- // sync
- RustResult store_sync(Pointer store, String userUuid, String serverUri);
+ EntityBuilder store_entity_builder_from_temp_id(Store store, String temp_id, RustError.ByReference err);
+ EntityBuilder store_entity_builder_from_entid(Store store, long entid, RustError.ByReference err);
+ void entity_builder_add_string(EntityBuilder builder, String kw, String value, RustError.ByReference err);
+ void entity_builder_add_long(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_add_ref(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_add_keyword(EntityBuilder builder, String kw, String value, RustError.ByReference err);
+ void entity_builder_add_boolean(EntityBuilder builder, String kw, int value, RustError.ByReference err);
+ void entity_builder_add_double(EntityBuilder builder, String kw, double value, RustError.ByReference err);
+ void entity_builder_add_timestamp(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_add_uuid(EntityBuilder builder, String kw, Pointer value, RustError.ByReference err);
+ void entity_builder_retract_string(EntityBuilder builder, String kw, String value, RustError.ByReference err);
+ void entity_builder_retract_long(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_retract_ref(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_retract_keyword(EntityBuilder builder, String kw, String value, RustError.ByReference err);
+ void entity_builder_retract_boolean(EntityBuilder builder, String kw, int value, RustError.ByReference err);
+ void entity_builder_retract_double(EntityBuilder builder, String kw, double value, RustError.ByReference err);
+ void entity_builder_retract_timestamp(EntityBuilder builder, String kw, long value, RustError.ByReference err);
+ void entity_builder_retract_uuid(EntityBuilder builder, String kw, Pointer value, RustError.ByReference err);
+ InProgressTransactionResult.ByValue entity_builder_transact(EntityBuilder builder);
+ TxReport entity_builder_commit(EntityBuilder builder, RustError.ByReference err);
// observers
- void store_register_observer(Pointer store, String key, Pointer attributes, int len, TxObserverCallback callback);
- void store_unregister_observer(Pointer store, String key);
- long store_entid_for_attribute(Pointer store, String attr);
+ void store_register_observer(Store store, String key, Pointer attributes, int len, TxObserverCallback callback);
+ void store_unregister_observer(Store store, String key);
+ long store_entid_for_attribute(Store store, String attr);
// Query Building
- Pointer store_query(Pointer store, String query);
- RustResult store_value_for_attribute(Pointer store, long entid, String attribute);
- void query_builder_bind_long(Pointer query, String var, long value);
- void query_builder_bind_ref(Pointer query, String var, long value);
- void query_builder_bind_ref_kw(Pointer query, String var, String value);
- void query_builder_bind_kw(Pointer query, String var, String value);
- void query_builder_bind_boolean(Pointer query, String var, int value);
- void query_builder_bind_double(Pointer query, String var, double value);
- void query_builder_bind_timestamp(Pointer query, String var, long value);
- void query_builder_bind_string(Pointer query, String var, String value);
- void query_builder_bind_uuid(Pointer query, String var, Pointer value);
+ QueryBuilder store_query(Store store, String query);
+ TypedValue store_value_for_attribute(Store store, long entid, String attribute, RustError.ByReference err);
+ void query_builder_bind_long(QueryBuilder query, String var, long value);
+ void query_builder_bind_ref(QueryBuilder query, String var, long value);
+ void query_builder_bind_ref_kw(QueryBuilder query, String var, String value);
+ void query_builder_bind_kw(QueryBuilder query, String var, String value);
+ void query_builder_bind_boolean(QueryBuilder query, String var, int value);
+ void query_builder_bind_double(QueryBuilder query, String var, double value);
+ void query_builder_bind_timestamp(QueryBuilder query, String var, long value);
+ void query_builder_bind_string(QueryBuilder query, String var, String value);
+ void query_builder_bind_uuid(QueryBuilder query, String var, Pointer value);
// Query Execution
- RustResult query_builder_execute(Pointer query);
- RustResult query_builder_execute_scalar(Pointer query);
- RustResult query_builder_execute_coll(Pointer query);
- RustResult query_builder_execute_tuple(Pointer query);
+ RelResult query_builder_execute(QueryBuilder query, RustError.ByReference err);
+ TypedValue query_builder_execute_scalar(QueryBuilder query, RustError.ByReference err);
+ TypedValueList query_builder_execute_coll(QueryBuilder query, RustError.ByReference err);
+ TypedValueList query_builder_execute_tuple(QueryBuilder query, RustError.ByReference err);
// Query Result Processing
- long typed_value_into_long(Pointer value);
- long typed_value_into_entid(Pointer value);
- String typed_value_into_kw(Pointer value);
- String typed_value_into_string(Pointer value);
- Pointer typed_value_into_uuid(Pointer value);
- int typed_value_into_boolean(Pointer value);
- double typed_value_into_double(Pointer value);
- long typed_value_into_timestamp(Pointer value);
- Pointer typed_value_value_type(Pointer value);
+ long typed_value_into_long(TypedValue value);
+ long typed_value_into_entid(TypedValue value);
+ Pointer typed_value_into_kw(TypedValue value);
+ Pointer typed_value_into_string(TypedValue value);
+ Pointer typed_value_into_uuid(TypedValue value);
+ int typed_value_into_boolean(TypedValue value);
+ double typed_value_into_double(TypedValue value);
+ long typed_value_into_timestamp(TypedValue value);
+ int typed_value_value_type(TypedValue value);
- Pointer row_at_index(Pointer rows, int index);
- Pointer typed_value_result_set_into_iter(Pointer rows);
- Pointer typed_value_result_set_iter_next(Pointer iter);
+ TypedValueList row_at_index(RelResult rows, int index);
+ RelResultIter typed_value_result_set_into_iter(RelResult rows);
+ TypedValueList typed_value_result_set_iter_next(RelResultIter iter);
- Pointer typed_value_list_into_iter(Pointer rows);
- Pointer typed_value_list_iter_next(Pointer iter);
+ TypedValueListIter typed_value_list_into_iter(TypedValueList rows);
+ TypedValue typed_value_list_iter_next(TypedValueListIter iter);
- Pointer value_at_index(Pointer rows, int index);
- long value_at_index_into_long(Pointer rows, int index);
- long value_at_index_into_entid(Pointer rows, int index);
- String value_at_index_into_kw(Pointer rows, int index);
- String value_at_index_into_string(Pointer rows, int index);
- Pointer value_at_index_into_uuid(Pointer rows, int index);
- int value_at_index_into_boolean(Pointer rows, int index);
- double value_at_index_into_double(Pointer rows, int index);
- long value_at_index_into_timestamp(Pointer rows, int index);
+ TypedValue value_at_index(TypedValueList rows, int index);
+ long value_at_index_into_long(TypedValueList rows, int index);
+ long value_at_index_into_entid(TypedValueList rows, int index);
+ Pointer value_at_index_into_kw(TypedValueList rows, int index);
+ Pointer value_at_index_into_string(TypedValueList rows, int index);
+ Pointer value_at_index_into_uuid(TypedValueList rows, int index);
+ int value_at_index_into_boolean(TypedValueList rows, int index);
+ double value_at_index_into_double(TypedValueList rows, int index);
+ long value_at_index_into_timestamp(TypedValueList rows, int index);
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java
index 84510440..94f4f285 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Mentat.java
@@ -20,7 +20,7 @@ import com.sun.jna.Pointer;
* This class provides all of the basic API that can be found in Mentat's Store struct.
* The raw pointer it holds is a pointer to a Store.
*/
-public class Mentat extends RustObject {
+public class Mentat extends RustObject {
static {
System.loadLibrary("mentat_ffi");
@@ -32,21 +32,21 @@ public class Mentat extends RustObject {
* @param dbPath The URI as a String of the store to open.
*/
public Mentat(String dbPath) {
- this.rawPointer = JNA.INSTANCE.store_open(dbPath);
+ this(JNA.INSTANCE.store_open(dbPath));
}
/**
* Open a connection to an in-memory Store.
*/
public Mentat() {
- this.rawPointer = JNA.INSTANCE.store_open("");
+ this(JNA.INSTANCE.store_open(""));
}
/**
* Create a new Mentat with the provided pointer to a Mentat Store
* @param rawPointer A pointer to a Mentat Store.
*/
- public Mentat(Pointer rawPointer) { this.rawPointer = rawPointer; }
+ public Mentat(JNA.Store rawPointer) { super(rawPointer); }
/**
* Add an attribute to the cache. The {@link CacheDirection} determines how that attribute can be
@@ -63,18 +63,19 @@ public class Mentat extends RustObject {
* BOTH adds an attribute such that it is cached in both directions.
*/
public void cache(String attribute, CacheDirection direction) {
- RustResult result = null;
+ RustError.ByReference err = new RustError.ByReference();
switch (direction) {
case FORWARD:
- result = JNA.INSTANCE.store_cache_attribute_forward(this.rawPointer, attribute);
+ JNA.INSTANCE.store_cache_attribute_forward(this.validPointer(), attribute, err);
+ break;
case REVERSE:
- result = JNA.INSTANCE.store_cache_attribute_reverse(this.rawPointer, attribute);
+ JNA.INSTANCE.store_cache_attribute_reverse(this.validPointer(), attribute, err);
+ break;
case BOTH:
- result = JNA.INSTANCE.store_cache_attribute_bi_directional(this.rawPointer, attribute);
- }
- if (result.isFailure()) {
- Log.e("Mentat", result.err);
+ JNA.INSTANCE.store_cache_attribute_bi_directional(this.validPointer(), attribute, err);
+ break;
}
+ err.logAndConsumeError("Mentat");
}
/**
@@ -84,15 +85,12 @@ public class Mentat extends RustObject {
* @return The {@link TxReport} of the completed transaction
*/
public TxReport transact(String transaction) {
- RustResult result = JNA.INSTANCE.store_transact(this.rawPointer, transaction);
- if (result.isFailure()) {
- Log.e("Mentat", result.err);
- return null;
- }
-
- if (result.isSuccess()) {
- return new TxReport(result.ok);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.TxReport report = JNA.INSTANCE.store_transact(this.validPointer(), transaction, err);
+ if (err.isSuccess()) {
+ return new TxReport(report);
} else {
+ err.logAndConsumeError("Mentat");
return null;
}
}
@@ -103,7 +101,7 @@ public class Mentat extends RustObject {
* @return The `Entid` associated with the attribute.
*/
public long entIdForAttribute(String attribute) {
- return JNA.INSTANCE.store_entid_for_attribute(this.rawPointer, attribute);
+ return JNA.INSTANCE.store_entid_for_attribute(this.validPointer(), attribute);
}
/**
@@ -112,7 +110,7 @@ public class Mentat extends RustObject {
* @return The {@link Query} representing the query that can be executed.
*/
public Query query(String query) {
- return new Query(JNA.INSTANCE.store_query(this.rawPointer, query));
+ return new Query(JNA.INSTANCE.store_query(this.validPointer(), query));
}
/**
@@ -123,16 +121,14 @@ public class Mentat extends RustObject {
* @return The {@link TypedValue} containing the value of the attribute for the entity.
*/
public TypedValue valueForAttributeOfEntity(String attribute, long entid) {
- RustResult result = JNA.INSTANCE.store_value_for_attribute(this.rawPointer, entid, attribute);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.TypedValue typedVal = JNA.INSTANCE.store_value_for_attribute(this.validPointer(), entid, attribute, err);
- if (result.isSuccess()) {
- return new TypedValue(result.ok);
- }
-
- if (result.isFailure()) {
- Log.e("Mentat", result.err);
+ if (err.isSuccess()) {
+ return new TypedValue(typedVal);
}
+ err.logAndConsumeError("Mentat");
return null;
}
@@ -149,11 +145,11 @@ public class Mentat extends RustObject {
// turn string array into int array
long[] attrEntids = new long[attributes.length];
for(int i = 0; i < attributes.length; i++) {
- attrEntids[i] = JNA.INSTANCE.store_entid_for_attribute(this.rawPointer, attributes[i]);
+ attrEntids[i] = JNA.INSTANCE.store_entid_for_attribute(this.validPointer(), attributes[i]);
}
final Pointer entidsNativeArray = new Memory(8 * attrEntids.length);
entidsNativeArray.write(0, attrEntids, 0, attrEntids.length);
- JNA.INSTANCE.store_register_observer(rawPointer, key, entidsNativeArray, attrEntids.length, callback);
+ JNA.INSTANCE.store_register_observer(validPointer(), key, entidsNativeArray, attrEntids.length, callback);
}
/**
@@ -164,10 +160,9 @@ public class Mentat extends RustObject {
* @param key String representing an identifier for the observer.
*/
public void unregisterObserver(String key) {
- JNA.INSTANCE.store_unregister_observer(rawPointer, key);
+ JNA.INSTANCE.store_unregister_observer(validPointer(), key);
}
-
/**
* Start a new transaction
*
@@ -176,15 +171,12 @@ public class Mentat extends RustObject {
* @return The {@link InProgress} used to manage the transaction
*/
public InProgress beginTransaction() {
- RustResult result = JNA.INSTANCE.store_begin_transaction(this.rawPointer);
- if (result.isSuccess()) {
- return new InProgress(result.ok);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.InProgress inProg = JNA.INSTANCE.store_begin_transaction(this.validPointer(), err);
+ if (err.isSuccess()) {
+ return new InProgress(inProg);
}
-
- if (result.isFailure()) {
- Log.i("Mentat", result.err);
- }
-
+ err.logAndConsumeError("Mentat");
return null;
}
@@ -197,15 +189,12 @@ public class Mentat extends RustObject {
* @return an {@link InProgressBuilder} for a new transaction.
*/
public InProgressBuilder entityBuilder() {
- RustResult result = JNA.INSTANCE.store_in_progress_builder(this.rawPointer);
- if (result.isSuccess()) {
- return new InProgressBuilder(result.ok);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.InProgressBuilder builder = JNA.INSTANCE.store_in_progress_builder(this.validPointer(), err);
+ if (err.isSuccess()) {
+ return new InProgressBuilder(builder);
}
-
- if (result.isFailure()) {
- Log.i("Mentat", result.err);
- }
-
+ err.logAndConsumeError("Mentat");
return null;
}
@@ -219,15 +208,12 @@ public class Mentat extends RustObject {
* @return an {@link EntityBuilder} for a new transaction.
*/
public EntityBuilder entityBuilder(long entid) {
- RustResult result = JNA.INSTANCE.store_entity_builder_from_entid(this.rawPointer, entid);
- if (result.isSuccess()) {
- return new EntityBuilder(result.ok);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.EntityBuilder builder = JNA.INSTANCE.store_entity_builder_from_entid(this.validPointer(), entid, err);
+ if (err.isSuccess()) {
+ return new EntityBuilder(builder);
}
-
- if (result.isFailure()) {
- Log.i("Mentat", result.err);
- }
-
+ err.logAndConsumeError("Mentat");
return null;
}
@@ -241,22 +227,17 @@ public class Mentat extends RustObject {
* @return an {@link EntityBuilder} for a new transaction.
*/
public EntityBuilder entityBuilder(String tempId) {
- RustResult result = JNA.INSTANCE.store_entity_builder_from_temp_id(this.rawPointer, tempId);
- if (result.isSuccess()) {
- return new EntityBuilder(result.ok);
+ RustError.ByReference err = new RustError.ByReference();
+ JNA.EntityBuilder builder = JNA.INSTANCE.store_entity_builder_from_temp_id(this.validPointer(), tempId, err);
+ if (err.isSuccess()) {
+ return new EntityBuilder(builder);
}
-
- if (result.isFailure()) {
- Log.i("Mentat", result.err);
- }
-
+ err.logAndConsumeError("Mentat");
return null;
}
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.store_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.Store p) {
+ JNA.INSTANCE.store_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Query.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Query.java
index 37eacb0a..aa389d2d 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Query.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/Query.java
@@ -12,8 +12,6 @@ package org.mozilla.mentat;
import android.util.Log;
-import com.sun.jna.Pointer;
-
import java.util.Date;
import java.util.UUID;
@@ -106,10 +104,10 @@ import java.util.UUID;
* });
*
*/
-public class Query extends RustObject {
+public class Query extends RustObject {
- public Query(Pointer pointer) {
- this.rawPointer = pointer;
+ public Query(JNA.QueryBuilder pointer) {
+ super(pointer);
}
/**
@@ -119,9 +117,9 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, long value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_long(this.rawPointer, varName, value);
+ public Query bind(String varName, long value) {
+ this.assertValidPointer();
+ JNA.INSTANCE.query_builder_bind_long(this.validPointer(), varName, value);
return this;
}
@@ -132,9 +130,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bindEntidReference(String varName, long value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_ref(this.rawPointer, varName, value);
+ public Query bindEntidReference(String varName, long value) {
+ JNA.INSTANCE.query_builder_bind_ref(this.validPointer(), varName, value);
return this;
}
@@ -145,9 +142,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bindKeywordReference(String varName, String value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_ref_kw(this.rawPointer, varName, value);
+ public Query bindKeywordReference(String varName, String value) {
+ JNA.INSTANCE.query_builder_bind_ref_kw(this.validPointer(), varName, value);
return this;
}
@@ -158,9 +154,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bindKeyword(String varName, String value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_kw(this.rawPointer, varName, value);
+ public Query bindKeyword(String varName, String value) {
+ JNA.INSTANCE.query_builder_bind_kw(this.validPointer(), varName, value);
return this;
}
@@ -171,9 +166,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, boolean value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_boolean(this.rawPointer, varName, value ? 1 : 0);
+ public Query bind(String varName, boolean value) {
+ JNA.INSTANCE.query_builder_bind_boolean(this.validPointer(), varName, value ? 1 : 0);
return this;
}
@@ -184,9 +178,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, double value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_double(this.rawPointer, varName, value);
+ public Query bind(String varName, double value) {
+ JNA.INSTANCE.query_builder_bind_double(this.validPointer(), varName, value);
return this;
}
@@ -197,10 +190,9 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, Date value) {
- this.validate();
+ public Query bind(String varName, Date value) {
long timestamp = value.getTime() * 1000;
- JNA.INSTANCE.query_builder_bind_timestamp(this.rawPointer, varName, timestamp);
+ JNA.INSTANCE.query_builder_bind_timestamp(this.validPointer(), varName, timestamp);
return this;
}
@@ -211,9 +203,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, String value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_string(this.rawPointer, varName, value);
+ public Query bind(String varName, String value) {
+ JNA.INSTANCE.query_builder_bind_string(this.validPointer(), varName, value);
return this;
}
@@ -224,9 +215,8 @@ public class Query extends RustObject {
* @param value The value to be bound
* @return This {@link Query} such that further function can be called.
*/
- Query bind(String varName, UUID value) {
- this.validate();
- JNA.INSTANCE.query_builder_bind_uuid(this.rawPointer, varName, getPointerForUUID(value));
+ public Query bind(String varName, UUID value) {
+ JNA.INSTANCE.query_builder_bind_uuid(this.validPointer(), varName, getPointerForUUID(value));
return this;
}
@@ -236,16 +226,14 @@ public class Query extends RustObject {
* TODO: Throw an exception if the query raw pointer has been consumed or the query fails to execute
* @param handler the handler to call with the results of this query
*/
- void run(final RelResultHandler handler) {
- this.validate();
- RustResult result = JNA.INSTANCE.query_builder_execute(rawPointer);
- rawPointer = null;
-
- if (result.isFailure()) {
- Log.e("Query", result.err);
+ public void run(final RelResultHandler handler) {
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.RelResult relResult = JNA.INSTANCE.query_builder_execute(this.consumePointer(), error);
+ if (error.isFailure()) {
+ Log.e("Query", error.consumeErrorMessage());
return;
}
- handler.handleRows(new RelResult(result.ok));
+ handler.handleRows(new RelResult(relResult));
}
/**
@@ -254,18 +242,17 @@ public class Query extends RustObject {
* TODO: Throw an exception if the query raw pointer has been consumed or the query fails to execute
* @param handler the handler to call with the results of this query
*/
- void run(final ScalarResultHandler handler) {
- this.validate();
- RustResult result = JNA.INSTANCE.query_builder_execute_scalar(rawPointer);
- rawPointer = null;
+ public void run(final ScalarResultHandler handler) {
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.TypedValue valOrNull = JNA.INSTANCE.query_builder_execute_scalar(consumePointer(), error);
- if (result.isFailure()) {
- Log.e("Query", result.err);
+ if (error.isFailure()) {
+ Log.e("Query", error.consumeErrorMessage());
return;
}
- if (result.isSuccess()) {
- handler.handleValue(new TypedValue(result.ok));
+ if (valOrNull != null) {
+ handler.handleValue(new TypedValue(valOrNull));
} else {
handler.handleValue(null);
}
@@ -277,16 +264,15 @@ public class Query extends RustObject {
* TODO: Throw an exception if the query raw pointer has been consumed or the query fails to execute
* @param handler the handler to call with the results of this query
*/
- void run(final CollResultHandler handler) {
- this.validate();
- RustResult result = JNA.INSTANCE.query_builder_execute_coll(rawPointer);
- rawPointer = null;
+ public void run(final CollResultHandler handler) {
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.TypedValueList collResult = JNA.INSTANCE.query_builder_execute_coll(this.consumePointer(), error);
- if (result.isFailure()) {
- Log.e("Query", result.err);
+ if (error.isFailure()) {
+ Log.e("Query", error.consumeErrorMessage());
return;
}
- handler.handleList(new CollResult(result.ok));
+ handler.handleList(new CollResult(collResult));
}
/**
@@ -295,28 +281,24 @@ public class Query extends RustObject {
* TODO: Throw an exception if the query raw pointer has been consumed or the query fails to execute
* @param handler the handler to call with the results of this query
*/
- void run(final TupleResultHandler handler) {
- this.validate();
- RustResult result = JNA.INSTANCE.query_builder_execute_tuple(rawPointer);
- rawPointer = null;
+ public void run(final TupleResultHandler handler) {
+ RustError.ByReference error = new RustError.ByReference();
+ JNA.TypedValueList tuple = JNA.INSTANCE.query_builder_execute_tuple(this.consumePointer(), error);
- if (result.isFailure()) {
- Log.e("Query", result.err);
+ if (error.isFailure()) {
+ Log.e("Query", error.consumeErrorMessage());
return;
}
- if (result.isSuccess()) {
- handler.handleRow(new TupleResult(result.ok));
+ if (tuple != null) {
+ handler.handleRow(new TupleResult(tuple));
} else {
handler.handleRow(null);
}
}
@Override
- public void close() {
- if (this.rawPointer == null) {
- return;
- }
- JNA.INSTANCE.query_builder_destroy(this.rawPointer);
+ protected void destroyPointer(JNA.QueryBuilder p) {
+ JNA.INSTANCE.query_builder_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResult.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResult.java
index 6e1eb4c1..61cae67f 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResult.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResult.java
@@ -10,8 +10,6 @@
package org.mozilla.mentat;
-import com.sun.jna.Pointer;
-
/**
* Wraps a `Rel` result from a Mentat query.
* A `Rel` result is a list of rows of `TypedValues`.
@@ -44,10 +42,10 @@ import com.sun.jna.Pointer;
*
* Note that iteration is consuming and can only be done once.
*/
-public class RelResult extends RustObject implements Iterable {
+public class RelResult extends RustObject implements Iterable {
- public RelResult(Pointer pointer) {
- this.rawPointer = pointer;
+ public RelResult(JNA.RelResult pointer) {
+ super(pointer);
}
/**
@@ -57,8 +55,8 @@ public class RelResult extends RustObject implements Iterable {
* @return The row at the requested index as a `TupleResult`, if present, or nil if there is no row at that index.
*/
public TupleResult rowAtIndex(int index) {
- this.validate();
- Pointer pointer = JNA.INSTANCE.row_at_index(this.rawPointer, index);
+ this.assertValidPointer();
+ JNA.TypedValueList pointer = JNA.INSTANCE.row_at_index(this.validPointer(), index);
if (pointer == null) {
return null;
}
@@ -68,19 +66,12 @@ public class RelResult extends RustObject implements Iterable {
@Override
public RelResultIterator iterator() {
- this.validate();
- Pointer iterPointer = JNA.INSTANCE.typed_value_result_set_into_iter(this.rawPointer);
- this.rawPointer = null;
- if (iterPointer == null) {
- return null;
- }
+ JNA.RelResultIter iterPointer = JNA.INSTANCE.typed_value_result_set_into_iter(this.consumePointer());
return new RelResultIterator(iterPointer);
}
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.typed_value_result_set_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.RelResult p) {
+ JNA.INSTANCE.typed_value_result_set_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResultIterator.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResultIterator.java
index 2ba37694..fea64b5a 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResultIterator.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RelResultIterator.java
@@ -12,43 +12,27 @@ package org.mozilla.mentat;
import com.sun.jna.Pointer;
-import java.util.Iterator;
/**
* Iterator for a {@link RelResult}
*/
-public class RelResultIterator extends RustObject implements Iterator {
+public class RelResultIterator extends RustIterator {
- Pointer nextPointer;
-
- RelResultIterator(Pointer iterator) {
- this.rawPointer = iterator;
- }
-
- private Pointer getNextPointer() {
- return JNA.INSTANCE.typed_value_result_set_iter_next(this.rawPointer);
+ RelResultIterator(JNA.RelResultIter iterator) {
+ super(iterator);
}
@Override
- public boolean hasNext() {
- this.nextPointer = getNextPointer();
- return this.nextPointer != null;
+ protected JNA.TypedValueList advanceIterator() {
+ return JNA.INSTANCE.typed_value_result_set_iter_next(this.validPointer());
}
@Override
- public TupleResult next() {
- Pointer next = this.nextPointer == null ? getNextPointer() : this.nextPointer;
- if (next == null) {
- return null;
- }
-
- return new TupleResult(next);
+ protected TupleResult constructItem(JNA.TypedValueList p) {
+ return new TupleResult(p);
}
-
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.typed_value_result_set_iter_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.RelResultIter p) {
+ JNA.INSTANCE.typed_value_result_set_iter_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustError.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustError.java
new file mode 100644
index 00000000..c403f8fe
--- /dev/null
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustError.java
@@ -0,0 +1,86 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * Copyright 2018 Mozilla
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ * this file except in compliance with the License. You may obtain a copy of the
+ * License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License. */
+
+package org.mozilla.mentat;
+
+import android.util.Log;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.Structure;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Represents a C struct containing a {@link Pointer}s and String that map to a Rust Result.
+ * A RustResult will contain either an ok value, OR an err value, or neither - never both.
+ */
+public class RustError extends Structure {
+ public static class ByReference extends RustError implements Structure.ByReference {
+ }
+
+ public static class ByValue extends RustError implements Structure.ByValue {
+ }
+ // It's probably a mistake to touch this, but it needs to be public for JNA
+ public Pointer message;
+
+ /**
+ * Does this represent success?
+ */
+ public boolean isSuccess() {
+ return this.message == null;
+ }
+
+ /**
+ * Does this represent failure?
+ */
+ public boolean isFailure() {
+ return this.message != null;
+ }
+
+ /**
+ * Get and consume the error message, or null if there is none.
+ */
+ public String consumeErrorMessage() {
+ String result = this.getErrorMessage();
+ if (this.message != null) {
+ JNA.INSTANCE.rust_c_string_destroy(this.message);
+ this.message = null;
+ }
+ return result;
+ }
+
+ /**
+ * Get the error message or null if there is none.
+ */
+ public String getErrorMessage() {
+ return this.message == null ? null : this.message.getString(0, "utf8");
+ }
+
+ @Override
+ protected List getFieldOrder() {
+ return Arrays.asList("message");
+ }
+
+ @Override
+ protected void finalize() {
+ if (this.message != null) {
+ JNA.INSTANCE.rust_c_string_destroy(this.message);
+ this.message = null;
+ }
+ }
+
+ /* package-local */
+ void logAndConsumeError(String tag) {
+ if (this.isFailure()) {
+ Log.e(tag, this.consumeErrorMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustIterator.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustIterator.java
new file mode 100644
index 00000000..171b7655
--- /dev/null
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustIterator.java
@@ -0,0 +1,70 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * Copyright 2018 Mozilla
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ * this file except in compliance with the License. You may obtain a copy of the
+ * License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License. */
+
+package org.mozilla.mentat;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.PointerType;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+// Common factored-out code shared by both RelResultIterator and CollResultIterator (and possibly
+// others in the future). This code is a bit error-prone so it's worth avoiding the duplication.
+abstract class RustIterator> extends RustObject implements Iterator {
+ // We own this if it is not null!
+ private ItemPtr nextPointer;
+
+ RustIterator(T pointer) {
+ super(pointer);
+ }
+
+ /** Implement by calling `JNA.INSTANCE.whatever_iter_next(this.validPointer());` */
+ abstract protected ItemPtr advanceIterator();
+ // Generally should be implemented as `new E(p)`.
+ abstract protected E constructItem(ItemPtr p);
+
+ private ItemPtr consumeNextPointer() {
+ if (this.nextPointer == null) {
+ throw new NullPointerException(this.getClass() + " nextPointer already consumed");
+ }
+ ItemPtr p = this.nextPointer;
+ this.nextPointer = null;
+ return p;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (this.nextPointer != null) {
+ return true;
+ }
+ this.nextPointer = advanceIterator();
+ return this.nextPointer != null;
+ }
+
+ @Override
+ public E next() {
+ ItemPtr next = this.nextPointer == null ? advanceIterator() : this.consumeNextPointer();
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ return this.constructItem(next);
+ }
+
+ @Override
+ public void close() {
+ if (this.nextPointer != null) {
+ // Clean up the next pointer by delegating to the iterated item -- this simplifies
+ // iterator implementations, and keeps the cleanup code in one place.
+ this.constructItem(this.consumeNextPointer());
+ }
+ super.close();
+ }
+}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustObject.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustObject.java
index bbc45bc0..27395c72 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustObject.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustObject.java
@@ -10,32 +10,58 @@
package org.mozilla.mentat;
+import android.util.Log;
+
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
+import com.sun.jna.PointerType;
-import java.io.Closeable;
import java.nio.ByteBuffer;
import java.util.UUID;
/**
* Base class that wraps an non-optional {@link Pointer} representing a pointer to a Rust object.
- * This class implements {@link Closeable} but does not provide an implementation, forcing all
+ * This class implements {@link AutoCloseable} but does not provide an implementation, forcing all
* subclasses to implement it. This ensures that all classes that inherit from RustObject
* will have their {@link Pointer} destroyed when the Java wrapper is destroyed.
*/
-abstract class RustObject implements Closeable {
- Pointer rawPointer;
+abstract class RustObject implements AutoCloseable {
+ // This should probably be private to let us better prevent usage mistakes (which lead to
+ // memory-unsafety).
+ private T rawPointer;
+
+ RustObject(T p) {
+ rawPointer = p;
+ }
/**
* Throws a {@link NullPointerException} if the underlying {@link Pointer} is null.
*/
- void validate() {
- if (this.rawPointer == null) {
+ void assertValidPointer() {
+ if (this.isConsumed()) {
throw new NullPointerException(this.getClass() + " consumed");
}
}
- public Pointer getPointerForUUID(UUID uuid) {
+ T validPointer() {
+ this.assertValidPointer();
+ return this.rawPointer;
+ }
+
+ boolean isConsumed() {
+ return this.rawPointer == null;
+ }
+
+ /* package-local */
+ T consumePointer() {
+ this.assertValidPointer();
+ T p = this.rawPointer;
+ this.rawPointer = null;
+ return p;
+ }
+
+ /* package-local */
+ static Pointer getPointerForUUID(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
@@ -45,11 +71,46 @@ abstract class RustObject implements Closeable {
return bytesNativeArray;
}
- public UUID getUUIDFromPointer(Pointer uuidPtr) {
- byte[] bytes = uuidPtr.getByteArray(0, 16);
- ByteBuffer bb = ByteBuffer.wrap(bytes);
- long high = bb.getLong();
- long low = bb.getLong();
- return new UUID(high, low);
+ /* package-local */
+ static UUID getAndConsumeUUIDPointer(Pointer uuidPtr) {
+ try {
+ byte[] bytes = uuidPtr.getByteArray(0, 16);
+ ByteBuffer bb = ByteBuffer.wrap(bytes);
+ long high = bb.getLong();
+ long low = bb.getLong();
+ return new UUID(high, low);
+ } finally {
+ JNA.INSTANCE.uuid_destroy(uuidPtr);
+ }
+ }
+
+ /* package-local */
+ static String getAndConsumeMentatString(Pointer stringPtr) {
+ if (stringPtr == null) {
+ return null;
+ }
+ try {
+ return stringPtr.getString(0, "utf8");
+ } finally {
+ JNA.INSTANCE.rust_c_string_destroy(stringPtr);
+ }
+ }
+
+ abstract protected void destroyPointer(T p);
+
+ @Override
+ public void close() {
+ if (this.rawPointer != null) {
+ this.destroyPointer(this.consumePointer());
+ }
+ }
+
+ @Override
+ protected void finalize() {
+ try {
+ this.close();
+ } catch (Exception e) {
+ Log.e("RustObject", e.toString());
+ }
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustResult.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustResult.java
deleted file mode 100644
index f2836bad..00000000
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/RustResult.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
- * Copyright 2018 Mozilla
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- * this file except in compliance with the License. You may obtain a copy of the
- * License at http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License. */
-
-package org.mozilla.mentat;
-
-import com.sun.jna.Pointer;
-import com.sun.jna.Structure;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Represents a C struct containing a {@link Pointer}s and String that map to a Rust Result.
- * A RustResult will contain either an ok value, OR an err value, or neither - never both.
- */
-public class RustResult extends Structure implements Closeable {
- public static class ByReference extends RustResult implements Structure.ByReference {
- }
-
- public static class ByValue extends RustResult implements Structure.ByValue {
- }
-
- public Pointer ok;
- public String err;
-
- /**
- * Is there an value attached to this result
- * @return true if a value is present, false otherwise
- */
- public boolean isSuccess() {
- return this.ok != null;
- }
-
- /**
- * Is there an error attached to this result?
- * @return true is an error is present, false otherwise
- */
- public boolean isFailure() {
- return this.err != null;
- }
-
- @Override
- protected List getFieldOrder() {
- return Arrays.asList("ok", "err");
- }
-
- @Override
- public void close() throws IOException {
- if (this.getPointer() != null) {
- JNA.INSTANCE.destroy(this.getPointer());
- }
- }
-}
\ No newline at end of file
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TupleResult.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TupleResult.java
index 316d7fd8..ef5a6ed2 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TupleResult.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TupleResult.java
@@ -35,10 +35,10 @@ import java.util.UUID;
*
* To iterate over the result set use standard iteration flows.
*/
-public class TupleResult extends RustObject {
+public class TupleResult extends RustObject {
- public TupleResult(Pointer pointer) {
- this.rawPointer = pointer;
+ public TupleResult(JNA.TypedValueList pointer) {
+ super(pointer);
}
/**
@@ -48,8 +48,7 @@ public class TupleResult extends RustObject {
* @return The {@link TypedValue} at that index.
*/
public TypedValue get(Integer index) {
- this.validate();
- Pointer pointer = JNA.INSTANCE.value_at_index(this.rawPointer, index);
+ JNA.TypedValue pointer = JNA.INSTANCE.value_at_index(this.validPointer(), index);
if (pointer == null) {
return null;
}
@@ -64,8 +63,7 @@ public class TupleResult extends RustObject {
* @return The {@link Long} at that index.
*/
public Long asLong(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_long(this.rawPointer, index);
+ return JNA.INSTANCE.value_at_index_into_long(this.validPointer(), index);
}
/**
@@ -76,8 +74,7 @@ public class TupleResult extends RustObject {
* @return The Entid at that index.
*/
public Long asEntid(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_entid(this.rawPointer, index);
+ return JNA.INSTANCE.value_at_index_into_entid(this.validPointer(), index);
}
/**
@@ -88,8 +85,7 @@ public class TupleResult extends RustObject {
* @return The keyword at that index.
*/
public String asKeyword(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_kw(this.rawPointer, index);
+ return getAndConsumeMentatString(JNA.INSTANCE.value_at_index_into_kw(this.validPointer(), index));
}
/**
@@ -100,8 +96,7 @@ public class TupleResult extends RustObject {
* @return The {@link Boolean} at that index.
*/
public Boolean asBool(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_boolean(this.rawPointer, index) == 0 ? false : true;
+ return JNA.INSTANCE.value_at_index_into_boolean(this.validPointer(), index) == 0 ? false : true;
}
/**
@@ -112,8 +107,7 @@ public class TupleResult extends RustObject {
* @return The {@link Double} at that index.
*/
public Double asDouble(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_double(this.rawPointer, index);
+ return JNA.INSTANCE.value_at_index_into_double(this.validPointer(), index);
}
/**
@@ -124,8 +118,7 @@ public class TupleResult extends RustObject {
* @return The {@link Date} at that index.
*/
public Date asDate(Integer index) {
- this.validate();
- return new Date(JNA.INSTANCE.value_at_index_into_timestamp(this.rawPointer, index) * 1_000);
+ return new Date(JNA.INSTANCE.value_at_index_into_timestamp(this.validPointer(), index) * 1_000);
}
/**
@@ -136,8 +129,8 @@ public class TupleResult extends RustObject {
* @return The {@link String} at that index.
*/
public String asString(Integer index) {
- this.validate();
- return JNA.INSTANCE.value_at_index_into_string(this.rawPointer, index);
+ return getAndConsumeMentatString(
+ JNA.INSTANCE.value_at_index_into_string(this.validPointer(), index));
}
/**
@@ -148,14 +141,12 @@ public class TupleResult extends RustObject {
* @return The {@link UUID} at that index.
*/
public UUID asUUID(Integer index) {
- this.validate();
- return getUUIDFromPointer(JNA.INSTANCE.value_at_index_into_uuid(this.rawPointer, index));
+ return getAndConsumeUUIDPointer(
+ JNA.INSTANCE.value_at_index_into_uuid(this.validPointer(), index));
}
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.typed_value_list_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.TypedValueList p) {
+ JNA.INSTANCE.typed_value_list_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChange.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChange.java
index 6b172bc0..691bd5ee 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChange.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChange.java
@@ -13,7 +13,6 @@ package org.mozilla.mentat;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
-import java.io.Closeable;
import java.util.Arrays;
import java.util.List;
@@ -22,27 +21,24 @@ import java.util.List;
* These changes contain the transaction identifier, a {@link Pointer} to a list of affected attribute
* Entids and the number of items that the list contains.
*/
-public class TxChange extends Structure implements Closeable {
+public class TxChange extends Structure {
public static class ByReference extends TxChange implements Structure.ByReference {
}
public static class ByValue extends TxChange implements Structure.ByValue {
}
- public int txid;
+ public long txid;
public Pointer changes;
- public int numberOfItems;
- // Used by the Swift counterpart, JNA does this for us automagically.
- // But we still need it here so that the number of fields and their order is correct
- public int changes_len;
+ public long changes_len;
/**
* Get the affected attributes for this transaction
* @return The changes as a list of Entids of affected attributes
*/
public List getChanges() {
- final long[] array = (long[]) changes.getLongArray(0, numberOfItems);
- Long[] longArray = new Long[numberOfItems];
+ final long[] array = (long[]) changes.getLongArray(0, (int)changes_len);
+ Long[] longArray = new Long[(int)changes_len];
int idx = 0;
for (long change: array) {
longArray[idx++] = change;
@@ -52,13 +48,8 @@ public class TxChange extends Structure implements Closeable {
@Override
protected List getFieldOrder() {
- return Arrays.asList("txid", "changes", "changes_len", "numberOfItems");
+ return Arrays.asList("txid", "changes", "changes_len");
}
- @Override
- public void close() {
- if (this.getPointer() != null) {
- JNA.INSTANCE.destroy(this.getPointer());
- }
- }
+ // Note: Rust has ownership of this data.
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChangeList.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChangeList.java
index c90d3982..daa42fd1 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChangeList.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxChangeList.java
@@ -12,14 +12,13 @@ package org.mozilla.mentat;
import com.sun.jna.Structure;
-import java.io.Closeable;
import java.util.Arrays;
import java.util.List;
/**
* Represents a C struct containing a list of {@link TxChange}s that occured.
*/
-public class TxChangeList extends Structure implements Closeable {
+public class TxChangeList extends Structure {
public static class ByReference extends TxChangeList implements Structure.ByReference {
}
@@ -27,30 +26,21 @@ public class TxChangeList extends Structure implements Closeable {
}
public TxChange.ByReference reports;
- public int numberOfItems;
- // Used by the Swift counterpart, JNA does this for us automagically.
- // // But we still need it here so that the number of fields and their order is correct
- public int len;
+ public long len;
/**
* Get the changes that occured
* @return a list of {@link TxChange}s for the notification
*/
public List getReports() {
- final TxChange[] array = (TxChange[]) reports.toArray(numberOfItems);
+ final TxChange[] array = (TxChange[]) reports.toArray((int)len);
return Arrays.asList(array);
}
@Override
protected List getFieldOrder() {
- return Arrays.asList("reports", "numberOfItems", "len");
+ return Arrays.asList("reports", "len");
}
- @Override
- public void close() {
- final TxChange[] nativeReports = (TxChange[]) reports.toArray(numberOfItems);
- for (TxChange nativeReport : nativeReports) {
- nativeReport.close();
- }
- }
+ // Note: Rust has ownership of this data.
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxReport.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxReport.java
index 2c82bb62..6782c9e5 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxReport.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TxReport.java
@@ -33,14 +33,14 @@ import java.util.Date;
* long aEntid = report.getEntidForTempId("a");
*}
*/
-public class TxReport extends RustObject {
+public class TxReport extends RustObject {
private Long txId;
private Date txInstant;
- public TxReport(Pointer pointer) {
- this.rawPointer = pointer;
+ public TxReport(JNA.TxReport pointer) {
+ super(pointer);
}
/**
@@ -49,7 +49,7 @@ public class TxReport extends RustObject {
*/
public Long getTxId() {
if (this.txId == null) {
- this.txId = JNA.INSTANCE.tx_report_get_entid(this.rawPointer);
+ this.txId = JNA.INSTANCE.tx_report_get_entid(this.validPointer());
}
return this.txId;
@@ -61,7 +61,7 @@ public class TxReport extends RustObject {
*/
public Date getTxInstant() {
if (this.txInstant == null) {
- this.txInstant = new Date(JNA.INSTANCE.tx_report_get_tx_instant(this.rawPointer));
+ this.txInstant = new Date(JNA.INSTANCE.tx_report_get_tx_instant(this.validPointer()));
}
return this.txInstant;
}
@@ -72,18 +72,19 @@ public class TxReport extends RustObject {
* @return The `Entid` for the temporary identifier, if present, otherwise `null`.
*/
public Long getEntidForTempId(String tempId) {
- Pointer longPointer = JNA.INSTANCE.tx_report_entity_for_temp_id(this.rawPointer, tempId);
+ Pointer longPointer = JNA.INSTANCE.tx_report_entity_for_temp_id(this.validPointer(), tempId);
if (longPointer == null) {
return null;
}
-
- return longPointer.getLong(0);
+ try {
+ return longPointer.getLong(0);
+ } finally {
+ JNA.INSTANCE.destroy(longPointer);
+ }
}
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.tx_report_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.TxReport p) {
+ JNA.INSTANCE.tx_report_destroy(p);
}
}
diff --git a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TypedValue.java b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TypedValue.java
index b73980bd..cb19ca8f 100644
--- a/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TypedValue.java
+++ b/sdks/android/Mentat/library/src/main/java/org/mozilla/mentat/TypedValue.java
@@ -25,16 +25,12 @@ import java.util.UUID;
* Also, due to the consuming nature of the FFI layer, this class also manages it's raw pointer, nilling it after calling the
* FFI conversion function so that the underlying base class can manage cleanup.
*/
-public class TypedValue extends RustObject {
+public class TypedValue extends RustObject {
private Object value;
- private boolean isConsumed() {
- return this.rawPointer == null;
- }
-
- public TypedValue(Pointer pointer) {
- this.rawPointer = pointer;
+ public TypedValue(JNA.TypedValue pointer) {
+ super(pointer);
}
/**
@@ -44,8 +40,7 @@ public class TypedValue extends RustObject {
*/
public Long asLong() {
if (!this.isConsumed()) {
- this.value = JNA.INSTANCE.typed_value_into_long(this.rawPointer);
- this.rawPointer = null;
+ this.value = JNA.INSTANCE.typed_value_into_long(this.consumePointer());
}
return (Long)value;
}
@@ -57,8 +52,7 @@ public class TypedValue extends RustObject {
*/
public Long asEntid() {
if (!this.isConsumed()) {
- this.value = JNA.INSTANCE.typed_value_into_entid(this.rawPointer);
- this.rawPointer = null;
+ this.value = JNA.INSTANCE.typed_value_into_entid(this.consumePointer());
}
return (Long)value;
}
@@ -70,8 +64,7 @@ public class TypedValue extends RustObject {
*/
public String asKeyword() {
if (!this.isConsumed()) {
- this.value = JNA.INSTANCE.typed_value_into_kw(this.rawPointer);
- this.rawPointer = null;
+ this.value = getAndConsumeMentatString(JNA.INSTANCE.typed_value_into_kw(this.consumePointer()));
}
return (String)value;
}
@@ -83,9 +76,8 @@ public class TypedValue extends RustObject {
*/
public Boolean asBoolean() {
if (!this.isConsumed()) {
- long value = JNA.INSTANCE.typed_value_into_boolean(this.rawPointer);
+ long value = JNA.INSTANCE.typed_value_into_boolean(this.consumePointer());
this.value = value == 0 ? false : true;
- this.rawPointer = null;
}
return (Boolean) this.value;
}
@@ -97,8 +89,7 @@ public class TypedValue extends RustObject {
*/
public Double asDouble() {
if (!this.isConsumed()) {
- this.value = JNA.INSTANCE.typed_value_into_double(this.rawPointer);
- this.rawPointer = null;
+ this.value = JNA.INSTANCE.typed_value_into_double(this.consumePointer());
}
return (Double)value;
}
@@ -110,8 +101,7 @@ public class TypedValue extends RustObject {
*/
public Date asDate() {
if (!this.isConsumed()) {
- this.value = new Date(JNA.INSTANCE.typed_value_into_timestamp(this.rawPointer) * 1_000);
- this.rawPointer = null;
+ this.value = new Date(JNA.INSTANCE.typed_value_into_timestamp(this.consumePointer()) * 1_000);
}
return (Date)this.value;
}
@@ -123,8 +113,8 @@ public class TypedValue extends RustObject {
*/
public String asString() {
if (!this.isConsumed()) {
- this.value = JNA.INSTANCE.typed_value_into_string(this.rawPointer);
- this.rawPointer = null;
+ this.value = getAndConsumeMentatString(
+ JNA.INSTANCE.typed_value_into_string(this.consumePointer()));
}
return (String)value;
}
@@ -136,16 +126,13 @@ public class TypedValue extends RustObject {
*/
public UUID asUUID() {
if (!this.isConsumed()) {
- this.value = getUUIDFromPointer(JNA.INSTANCE.typed_value_into_uuid(this.rawPointer));
- this.rawPointer = null;
+ this.value = getAndConsumeUUIDPointer(JNA.INSTANCE.typed_value_into_uuid(this.consumePointer()));
}
return (UUID)this.value;
}
@Override
- public void close() {
- if (this.rawPointer != null) {
- JNA.INSTANCE.typed_value_destroy(this.rawPointer);
- }
+ protected void destroyPointer(JNA.TypedValue p) {
+ JNA.INSTANCE.typed_value_destroy(p);
}
}
diff --git a/sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj b/sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj
index dad9a961..cdb4c6f7 100644
--- a/sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj
+++ b/sdks/swift/Mentat/Mentat.xcodeproj/project.pbxproj
@@ -11,7 +11,7 @@
7B64E44D209094520063909F /* InProgressBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B64E44A209094510063909F /* InProgressBuilder.swift */; };
7B64E44E209094520063909F /* EntityBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B64E44B209094510063909F /* EntityBuilder.swift */; };
7B64E44F209094520063909F /* InProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B64E44C209094520063909F /* InProgress.swift */; };
- 7B74483D208DF667006CFFB0 /* Result+Unwrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B74483C208DF667006CFFB0 /* Result+Unwrap.swift */; };
+ 7B74483D208DF667006CFFB0 /* RustError+Unwrap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B74483C208DF667006CFFB0 /* RustError+Unwrap.swift */; };
7BAE75A42089022B00895D37 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BAE75A32089022B00895D37 /* libsqlite3.tbd */; };
7BDB96942077C299009D0651 /* Mentat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7BDB968A2077C299009D0651 /* Mentat.framework */; };
7BDB96992077C299009D0651 /* MentatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96982077C299009D0651 /* MentatTests.swift */; };
@@ -29,6 +29,8 @@
7BDB96C9207B735A009D0651 /* fixtures in Resources */ = {isa = PBXBuildFile; fileRef = 7BDB96C8207B735A009D0651 /* fixtures */; };
7BDB96CC207B7684009D0651 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDB96CB207B7684009D0651 /* Errors.swift */; };
7BEB7D2C207D03DA000369AD /* TxReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BEB7D2B207D03DA000369AD /* TxReport.swift */; };
+ D53A75B820D2DD3D00BAD7EA /* String+Destroying.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53A75B720D2DD3D00BAD7EA /* String+Destroying.swift */; };
+ D574353420DC26C7007C92EB /* UUID+Destroying.swift in Sources */ = {isa = PBXBuildFile; fileRef = D574353320DC26C7007C92EB /* UUID+Destroying.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -58,7 +60,7 @@
7B64E44A209094510063909F /* InProgressBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InProgressBuilder.swift; sourceTree = ""; };
7B64E44B209094510063909F /* EntityBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EntityBuilder.swift; sourceTree = ""; };
7B64E44C209094520063909F /* InProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InProgress.swift; sourceTree = ""; };
- 7B74483C208DF667006CFFB0 /* Result+Unwrap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Result+Unwrap.swift"; path = "Mentat/Extensions/Result+Unwrap.swift"; sourceTree = SOURCE_ROOT; };
+ 7B74483C208DF667006CFFB0 /* RustError+Unwrap.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "RustError+Unwrap.swift"; path = "Mentat/Extensions/RustError+Unwrap.swift"; sourceTree = SOURCE_ROOT; };
7BAE75A32089022B00895D37 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; };
7BDB968A2077C299009D0651 /* Mentat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Mentat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7BDB968D2077C299009D0651 /* Mentat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Mentat.h; sourceTree = ""; };
@@ -81,6 +83,8 @@
7BDB96CB207B7684009D0651 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; };
7BEB7D23207BE2AF000369AD /* libmentat_ffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libmentat_ffi.a; path = ../../../target/universal/release/libmentat_ffi.a; sourceTree = ""; };
7BEB7D2B207D03DA000369AD /* TxReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TxReport.swift; sourceTree = ""; };
+ D53A75B720D2DD3D00BAD7EA /* String+Destroying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Destroying.swift"; sourceTree = ""; };
+ D574353320DC26C7007C92EB /* UUID+Destroying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UUID+Destroying.swift"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -193,8 +197,10 @@
7BDB96C42077D346009D0651 /* Extensions */ = {
isa = PBXGroup;
children = (
- 7B74483C208DF667006CFFB0 /* Result+Unwrap.swift */,
+ 7B74483C208DF667006CFFB0 /* RustError+Unwrap.swift */,
+ D574353320DC26C7007C92EB /* UUID+Destroying.swift */,
7BDB96C52077D346009D0651 /* Date+Int64.swift */,
+ D53A75B720D2DD3D00BAD7EA /* String+Destroying.swift */,
);
path = Extensions;
sourceTree = "";
@@ -331,6 +337,7 @@
buildActionMask = 2147483647;
files = (
7BDB96B32077C38E009D0651 /* RustObject.swift in Sources */,
+ D53A75B820D2DD3D00BAD7EA /* String+Destroying.swift in Sources */,
7BDB96C62077D347009D0651 /* Date+Int64.swift in Sources */,
7BEB7D2C207D03DA000369AD /* TxReport.swift in Sources */,
7BDB96B42077C38E009D0651 /* OptionalRustObject.swift in Sources */,
@@ -339,10 +346,11 @@
7BDB96CC207B7684009D0651 /* Errors.swift in Sources */,
7BDB96B02077C38E009D0651 /* Mentat.swift in Sources */,
7BDB96B72077C38E009D0651 /* TypedValue.swift in Sources */,
+ D574353420DC26C7007C92EB /* UUID+Destroying.swift in Sources */,
7B64E44E209094520063909F /* EntityBuilder.swift in Sources */,
7B64E44D209094520063909F /* InProgressBuilder.swift in Sources */,
7BDB96B52077C38E009D0651 /* TupleResult.swift in Sources */,
- 7B74483D208DF667006CFFB0 /* Result+Unwrap.swift in Sources */,
+ 7B74483D208DF667006CFFB0 /* RustError+Unwrap.swift in Sources */,
7B64E44F209094520063909F /* InProgress.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
diff --git a/sdks/swift/Mentat/Mentat/Core/TypedValue.swift b/sdks/swift/Mentat/Mentat/Core/TypedValue.swift
index 1963ec5f..7ec73788 100644
--- a/sdks/swift/Mentat/Mentat/Core/TypedValue.swift
+++ b/sdks/swift/Mentat/Mentat/Core/TypedValue.swift
@@ -82,7 +82,7 @@ open class TypedValue: OptionalRustObject {
}
if !self.isConsumed() {
- self.value = String(cString: typed_value_into_kw(self.raw!))
+ self.value = String(destroyingRustString: typed_value_into_kw(self.raw!))
}
return self.value as! String
}
@@ -152,7 +152,7 @@ open class TypedValue: OptionalRustObject {
}
if !self.isConsumed() {
- self.value = String(cString: typed_value_into_string(self.raw!))
+ self.value = String(destroyingRustString: typed_value_into_string(self.raw!));
}
return self.value as! String
}
@@ -169,8 +169,8 @@ open class TypedValue: OptionalRustObject {
}
if !self.isConsumed() {
- let bytes = typed_value_into_uuid(self.raw!).pointee
- self.value = UUID(uuid: bytes)
+ let bytes = typed_value_into_uuid(self.raw!);
+ self.value = UUID(destroyingRustUUID: bytes);
}
return self.value as! UUID?
}
diff --git a/sdks/swift/Mentat/Mentat/Extensions/Result+Unwrap.swift b/sdks/swift/Mentat/Mentat/Extensions/Result+Unwrap.swift
deleted file mode 100644
index 7204067b..00000000
--- a/sdks/swift/Mentat/Mentat/Extensions/Result+Unwrap.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2018 Mozilla
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
- * this file except in compliance with the License. You may obtain a copy of the
- * License at http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software distributed
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations under the License. */
-
-import Foundation
-import MentatStore
-
-public extension Result {
- /**
- Force unwraps a result.
- Expects there to be a value attached and throws an error is there is not.
-
- - Throws: `ResultError.error` if the result contains an error
- - Throws: `ResultError.empty` if the result contains no error but also no result.
-
- - Returns: The pointer to the successful result value.
- */
- @discardableResult public func unwrap() throws -> UnsafeMutableRawPointer {
- guard let success = self.ok else {
- if let error = self.err {
- throw ResultError.error(message: String(cString: error))
- }
- throw ResultError.empty
- }
- return success
- }
-
- /**
- Unwraps an optional result, yielding either a successful value or a nil.
-
- - Throws: `ResultError.error` if the result contains an error
-
- - Returns: The pointer to the successful result value, or nil if no value is present.
- */
- @discardableResult public func tryUnwrap() throws -> UnsafeMutableRawPointer? {
- guard let success = self.ok else {
- if let error = self.err {
- throw ResultError.error(message: String(cString: error))
- }
- return nil
- }
- return success
- }
-}
diff --git a/sdks/swift/Mentat/Mentat/Extensions/RustError+Unwrap.swift b/sdks/swift/Mentat/Mentat/Extensions/RustError+Unwrap.swift
new file mode 100644
index 00000000..90825dc8
--- /dev/null
+++ b/sdks/swift/Mentat/Mentat/Extensions/RustError+Unwrap.swift
@@ -0,0 +1,48 @@
+/* Copyright 2018 Mozilla
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ * this file except in compliance with the License. You may obtain a copy of the
+ * License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License. */
+
+import Foundation
+import MentatStore
+
+extension RustError {
+
+ @discardableResult
+ public static func unwrap(_ callback: (UnsafeMutablePointer) throws -> OpaquePointer?) throws -> OpaquePointer {
+ var err = RustError(message: nil)
+ guard let result = try callback(&err) else {
+ if let message = err.message {
+ throw ResultError.error(message: String(destroyingRustString: message))
+ }
+ throw ResultError.empty
+ }
+ return result;
+ }
+
+ @discardableResult
+ public static func tryUnwrap(_ callback: (UnsafeMutablePointer) throws -> OpaquePointer?) throws -> OpaquePointer? {
+ var err = RustError(message: nil)
+ guard let result = try callback(&err) else {
+ if let message = err.message {
+ throw ResultError.error(message: String(destroyingRustString: message))
+ }
+ return nil
+ }
+ return result;
+ }
+
+ public static func withErrorCheck(_ callback: (UnsafeMutablePointer) throws -> Void) throws {
+ var err = RustError(message: nil)
+ try callback(&err);
+ if let message = err.message {
+ throw ResultError.error(message: String(destroyingRustString: message))
+ }
+ }
+}
+
diff --git a/sdks/swift/Mentat/Mentat/Extensions/String+Destroying.swift b/sdks/swift/Mentat/Mentat/Extensions/String+Destroying.swift
new file mode 100644
index 00000000..5d8c0729
--- /dev/null
+++ b/sdks/swift/Mentat/Mentat/Extensions/String+Destroying.swift
@@ -0,0 +1,21 @@
+/* Copyright 2018 Mozilla
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ * this file except in compliance with the License. You may obtain a copy of the
+ * License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License. */
+
+
+import Foundation
+import MentatStore
+
+public extension String {
+ /** Helper to construct a String from a Rust string without leaking it. */
+ public init(destroyingRustString rustCString: UnsafeMutablePointer) {
+ defer { rust_c_string_destroy(rustCString); }
+ self.init(cString: rustCString)
+ }
+}
diff --git a/sdks/swift/Mentat/Mentat/Extensions/UUID+Destroying.swift b/sdks/swift/Mentat/Mentat/Extensions/UUID+Destroying.swift
new file mode 100644
index 00000000..e6c47b33
--- /dev/null
+++ b/sdks/swift/Mentat/Mentat/Extensions/UUID+Destroying.swift
@@ -0,0 +1,21 @@
+/* Copyright 2018 Mozilla
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use
+ * this file except in compliance with the License. You may obtain a copy of the
+ * License at http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software distributed
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License. */
+
+
+import Foundation
+import MentatStore
+
+public extension UUID {
+ /** Helper to construct a UUID from a Rust [u8; 16] without leaking it. */
+ public init(destroyingRustUUID rawUUID: UnsafeMutablePointer) {
+ defer { uuid_destroy(rawUUID); }
+ self.init(uuid: rawUUID.pointee)
+ }
+}
diff --git a/sdks/swift/Mentat/Mentat/Mentat.swift b/sdks/swift/Mentat/Mentat/Mentat.swift
index d46450b6..2bd569e6 100644
--- a/sdks/swift/Mentat/Mentat/Mentat.swift
+++ b/sdks/swift/Mentat/Mentat/Mentat.swift
@@ -77,14 +77,16 @@ open class Mentat: RustObject {
- Throws: `ResultError.error` if an error occured while trying to cache the attribute.
*/
open func cache(attribute: String, direction: CacheDirection) throws {
- switch direction {
- case .forward:
- try store_cache_attribute_forward(self.raw, attribute).pointee.tryUnwrap()
- case .reverse:
- try store_cache_attribute_reverse(self.raw, attribute).pointee.tryUnwrap()
- case .both:
- try store_cache_attribute_bi_directional(self.raw, attribute).pointee.tryUnwrap()
- }
+ try RustError.withErrorCheck({err in
+ switch direction {
+ case .forward:
+ store_cache_attribute_forward(self.raw, attribute, err)
+ case .reverse:
+ store_cache_attribute_reverse(self.raw, attribute, err)
+ case .both:
+ store_cache_attribute_bi_directional(self.raw, attribute, err)
+ }
+ });
}
/**
@@ -96,8 +98,7 @@ open class Mentat: RustObject {
- Returns: The `TxReport` of the completed transaction
*/
open func transact(transaction: String) throws -> TxReport {
- let result = store_transact(self.raw, transaction).pointee
- return TxReport(raw: try result.unwrap())
+ return TxReport(raw: try RustError.unwrap({err in store_transact(self.raw, transaction, err) }))
}
/**
@@ -109,8 +110,7 @@ open class Mentat: RustObject {
- Returns: The `InProgress` used to manage the transaction
*/
open func beginTransaction() throws -> InProgress {
- let result = store_begin_transaction(self.raw).pointee;
- return InProgress(raw: try result.unwrap())
+ return InProgress(raw: try RustError.unwrap({err in store_begin_transaction(self.raw, err) }));
}
/**
@@ -122,8 +122,7 @@ open class Mentat: RustObject {
- Returns: an `InProgressBuilder` for this `InProgress`
*/
open func entityBuilder() throws -> InProgressBuilder {
- let result = store_in_progress_builder(self.raw).pointee
- return InProgressBuilder(raw: try result.unwrap())
+ return InProgressBuilder(raw: try RustError.unwrap({err in store_in_progress_builder(self.raw, err) }))
}
/**
@@ -138,8 +137,8 @@ open class Mentat: RustObject {
- Returns: an `EntityBuilder` for this `InProgress`
*/
open func entityBuilder(forEntid entid: Entid) throws -> EntityBuilder {
- let result = store_entity_builder_from_entid(self.raw, entid).pointee
- return EntityBuilder(raw: try result.unwrap())
+ return EntityBuilder(raw: try RustError.unwrap({err in
+ store_entity_builder_from_entid(self.raw, entid, err) }))
}
/**
@@ -154,8 +153,9 @@ open class Mentat: RustObject {
- Returns: an `EntityBuilder` for this `InProgress`
*/
open func entityBuilder(forTempId tempId: String) throws -> EntityBuilder {
- let result = store_entity_builder_from_temp_id(self.raw, tempId).pointee
- return EntityBuilder(raw: try result.unwrap())
+ return EntityBuilder(raw: try RustError.unwrap({err in
+ store_entity_builder_from_temp_id(self.raw, tempId, err)
+ }))
}
/**
@@ -189,8 +189,9 @@ open class Mentat: RustObject {
- Returns: The `TypedValue` containing the value of the attribute for the entity.
*/
open func value(forAttribute attribute: String, ofEntity entid: Entid) throws -> TypedValue? {
- let result = store_value_for_attribute(self.raw, entid, attribute).pointee
- return TypedValue(raw: try result.unwrap())
+ return TypedValue(raw: try RustError.unwrap({err in
+ store_value_for_attribute(self.raw, entid, attribute, err)
+ }));
}
// Destroys the pointer by passing it back into Rust to be cleaned up
diff --git a/sdks/swift/Mentat/Mentat/Query/Query.swift b/sdks/swift/Mentat/Mentat/Query/Query.swift
index 765f50eb..480821ba 100644
--- a/sdks/swift/Mentat/Mentat/Query/Query.swift
+++ b/sdks/swift/Mentat/Mentat/Query/Query.swift
@@ -245,14 +245,15 @@ open class Query: OptionalRustObject {
- Throws: `PointerError.pointerConsumed` if the underlying raw pointer has already consumed, which will occur if the query has previously been executed.
*/
open func run(callback: @escaping (RelResult?) -> Void) throws {
- let result = query_builder_execute(try! self.validPointer())
+ var error = RustError(message: nil)
+ let result = query_builder_execute(try! self.validPointer(), &error);
self.raw = nil
- if let err = result.pointee.err {
- let message = String(cString: err)
+ if let err = error.message {
+ let message = String(destroyingRustString: err)
throw QueryError.executionFailed(message: message)
}
- guard let results = result.pointee.ok else {
+ guard let results = result else {
callback(nil)
return
}
@@ -269,18 +270,19 @@ open class Query: OptionalRustObject {
- Throws: `PointerError.pointerConsumed` if the underlying raw pointer has already consumed, which will occur if the query has previously been executed.
*/
open func runScalar(callback: @escaping (TypedValue?) -> Void) throws {
- let result = query_builder_execute_scalar(try! self.validPointer())
+ var error = RustError(message: nil)
+ let result = query_builder_execute_scalar(try! self.validPointer(), &error)
self.raw = nil
- if let err = result.pointee.err {
- let message = String(cString: err)
+ if let err = error.message {
+ let message = String(destroyingRustString: err)
throw QueryError.executionFailed(message: message)
}
- guard let results = result.pointee.ok else {
+ guard let results = result else {
callback(nil)
return
}
- callback(TypedValue(raw: OpaquePointer(results)))
+ callback(TypedValue(raw: results))
}
/**
@@ -293,14 +295,15 @@ open class Query: OptionalRustObject {
- Throws: `PointerError.pointerConsumed` if the underlying raw pointer has already consumed, which will occur if the query has previously been executed.
*/
open func runColl(callback: @escaping (ColResult?) -> Void) throws {
- let result = query_builder_execute_coll(try! self.validPointer())
+ var error = RustError(message: nil)
+ let result = query_builder_execute_coll(try! self.validPointer(), &error)
self.raw = nil
- if let err = result.pointee.err {
- let message = String(cString: err)
- throw QueryError.executionFailed(message: message)
+ if let err = error.message {
+ let message = String(destroyingRustString: err)
+ throw QueryError.executionFailed(message: message)
}
- guard let results = result.pointee.ok else {
+ guard let results = result else {
callback(nil)
return
}
@@ -317,18 +320,19 @@ open class Query: OptionalRustObject {
- Throws: `PointerError.pointerConsumed` if the underlying raw pointer has already consumed, which will occur if the query has previously been executed.
*/
open func runTuple(callback: @escaping (TupleResult?) -> Void) throws {
- let result = query_builder_execute_tuple(try! self.validPointer())
+ var error = RustError(message: nil)
+ let result = query_builder_execute_tuple(try! self.validPointer(), &error)
self.raw = nil
- if let err = result.pointee.err {
- let message = String(cString: err)
+ if let err = error.message {
+ let message = String(destroyingRustString: err)
throw QueryError.executionFailed(message: message)
}
- guard let results = result.pointee.ok else {
+ guard let results = result else {
callback(nil)
return
}
- callback(TupleResult(raw: OpaquePointer(results)))
+ callback(TupleResult(raw: results))
}
override open func cleanup(pointer: OpaquePointer) {
diff --git a/sdks/swift/Mentat/Mentat/Query/RelResult.swift b/sdks/swift/Mentat/Mentat/Query/RelResult.swift
index a5f606b7..7b72b186 100644
--- a/sdks/swift/Mentat/Mentat/Query/RelResult.swift
+++ b/sdks/swift/Mentat/Mentat/Query/RelResult.swift
@@ -55,7 +55,7 @@ open class RelResult: OptionalRustObject {
}
override open func cleanup(pointer: OpaquePointer) {
- destroy(UnsafeMutableRawPointer(pointer))
+ typed_value_result_set_destroy(pointer)
}
}
diff --git a/sdks/swift/Mentat/Mentat/Query/TupleResult.swift b/sdks/swift/Mentat/Mentat/Query/TupleResult.swift
index 00c1cb2a..d41a4f92 100644
--- a/sdks/swift/Mentat/Mentat/Query/TupleResult.swift
+++ b/sdks/swift/Mentat/Mentat/Query/TupleResult.swift
@@ -77,7 +77,8 @@ open class TupleResult: OptionalRustObject {
- Returns: The keyword `String` at that index.
*/
open func asKeyword(index: Int) -> String {
- return String(cString: value_at_index_into_kw(self.raw!, Int32(index)))
+ let str = value_at_index_into_kw(self.raw!, Int32(index));
+ return String(destroyingRustString: str);
}
/**
@@ -129,7 +130,8 @@ open class TupleResult: OptionalRustObject {
- Returns: The `String` at that index.
*/
open func asString(index: Int) -> String {
- return String(cString: value_at_index_into_string(self.raw!, Int32(index)))
+ let str = value_at_index_into_string(self.raw!, Int32(index));
+ return String(destroyingRustString: str)
}
/**
@@ -142,7 +144,8 @@ open class TupleResult: OptionalRustObject {
- Returns: The `UUID` at that index.
*/
open func asUUID(index: Int) -> UUID? {
- return UUID(uuid: value_at_index_into_uuid(self.raw!, Int32(index)).pointee)
+ let uuid = value_at_index_into_uuid(self.raw!, Int32(index));
+ return UUID(destroyingRustUUID: uuid)
}
override open func cleanup(pointer: OpaquePointer) {
diff --git a/sdks/swift/Mentat/Mentat/Rust/RustObject.swift b/sdks/swift/Mentat/Mentat/Rust/RustObject.swift
index 64252f04..80fea717 100644
--- a/sdks/swift/Mentat/Mentat/Rust/RustObject.swift
+++ b/sdks/swift/Mentat/Mentat/Rust/RustObject.swift
@@ -38,7 +38,7 @@ open class RustObject: Destroyable {
}
self.raw = r
}
-
+
public func getRaw() -> OpaquePointer {
return self.raw
}
@@ -46,7 +46,7 @@ open class RustObject: Destroyable {
deinit {
self.cleanup(pointer: self.raw)
}
-
+
open func cleanup(pointer: OpaquePointer) {
fatalError("\(cleanup) is not implemented.")
}
diff --git a/sdks/swift/Mentat/Mentat/Transact/EntityBuilder.swift b/sdks/swift/Mentat/Mentat/Transact/EntityBuilder.swift
index 750afc7c..bfb15a88 100644
--- a/sdks/swift/Mentat/Mentat/Transact/EntityBuilder.swift
+++ b/sdks/swift/Mentat/Mentat/Transact/EntityBuilder.swift
@@ -69,7 +69,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/long`.
*/
open func add(keyword: String, long value: Int64) throws {
- try entity_builder_add_long(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_long(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -84,7 +86,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/ref`.
*/
open func add(keyword: String, reference value: Int64) throws {
- try entity_builder_add_ref(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_ref(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -99,7 +103,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/keyword`.
*/
open func add(keyword: String, keyword value: String) throws {
- try entity_builder_add_keyword(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_keyword(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -114,7 +120,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/boolean`.
*/
open func add(keyword: String, boolean value: Bool) throws {
- try entity_builder_add_boolean(try self.validPointer(), keyword, value ? 1 : 0).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_boolean(try self.validPointer(), keyword, value ? 1 : 0, err)
+ })
}
/**
@@ -129,7 +137,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/double`.
*/
open func add(keyword: String, double value: Double) throws {
- try entity_builder_add_double(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_double(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -145,7 +155,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/instant`.
*/
open func add(keyword: String, date value: Date) throws {
- try entity_builder_add_timestamp(try self.validPointer(), keyword, value.toMicroseconds()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_timestamp(try self.validPointer(), keyword, value.toMicroseconds(), err)
+ })
}
/**
@@ -160,7 +172,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/string`.
*/
open func add(keyword: String, string value: String) throws {
- try entity_builder_add_string(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_string(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -177,7 +191,9 @@ open class EntityBuilder: OptionalRustObject {
open func add(keyword: String, uuid value: UUID) throws {
var rawUuid = value.uuid
let _ = try withUnsafePointer(to: &rawUuid) { uuidPtr in
- try entity_builder_add_uuid(try self.validPointer(), keyword, uuidPtr).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_add_uuid(try self.validPointer(), keyword, uuidPtr, err)
+ })
}
}
@@ -193,7 +209,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/long`.
*/
open func retract(keyword: String, long value: Int64) throws {
- try entity_builder_retract_long(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_long(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -208,7 +226,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/ref`.
*/
open func retract(keyword: String, reference value: Int64) throws {
- try entity_builder_retract_ref(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_ref(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -223,7 +243,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/keyword`.
*/
open func retract(keyword: String, keyword value: String) throws {
- try entity_builder_retract_keyword(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_keyword(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -238,7 +260,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/boolean`.
*/
open func retract(keyword: String, boolean value: Bool) throws {
- try entity_builder_retract_boolean(try self.validPointer(), keyword, value ? 1 : 0).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_boolean(try self.validPointer(), keyword, value ? 1 : 0, err)
+ })
}
/**
@@ -253,7 +277,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/double`.
*/
open func retract(keyword: String, double value: Double) throws {
- try entity_builder_retract_double(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_double(try self.validPointer(), keyword, value, err)
+ })
}
/**
@@ -268,7 +294,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/instant`.
*/
open func retract(keyword: String, date value: Date) throws {
- try entity_builder_retract_timestamp(try self.validPointer(), keyword, value.toMicroseconds()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_timestamp(try self.validPointer(), keyword, value.toMicroseconds(), err)
+ })
}
/**
@@ -283,7 +311,9 @@ open class EntityBuilder: OptionalRustObject {
is not `:db.type/string`.
*/
open func retract(keyword: String, string value: String) throws {
- try entity_builder_retract_string(try self.validPointer(), keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_string(try self.validPointer(), keyword, value, err)
+ })
}
@@ -301,7 +331,9 @@ open class EntityBuilder: OptionalRustObject {
open func retract(keyword: String, uuid value: UUID) throws {
var rawUuid = value.uuid
let _ = try withUnsafePointer(to: &rawUuid) { uuidPtr in
- try entity_builder_retract_uuid(try self.validPointer(), keyword, uuidPtr).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ entity_builder_retract_uuid(try self.validPointer(), keyword, uuidPtr, err)
+ })
}
}
@@ -323,9 +355,12 @@ open class EntityBuilder: OptionalRustObject {
defer {
self.raw = nil
}
- let result = entity_builder_transact(try self.validPointer()).pointee
+ let result = entity_builder_transact(try self.validPointer());
let inProgress = InProgress(raw: result.inProgress)
- guard let report = try result.result.pointee.tryUnwrap() else {
+ if let errorMessage = result.error.message {
+ throw ResultError.error(message: String(destroyingRustString: errorMessage))
+ }
+ guard let report = result.txReport else {
return (inProgress, nil)
}
return (inProgress, TxReport(raw: report))
@@ -346,9 +381,11 @@ open class EntityBuilder: OptionalRustObject {
defer {
self.raw = nil
}
- return TxReport(raw: try entity_builder_commit(try self.validPointer()).pointee.unwrap())
+ return TxReport(raw: try RustError.unwrap({ err in
+ entity_builder_commit(try self.validPointer(), err)
+ }))
}
-
+
override open func cleanup(pointer: OpaquePointer) {
entity_builder_destroy(pointer)
}
diff --git a/sdks/swift/Mentat/Mentat/Transact/InProgress.swift b/sdks/swift/Mentat/Mentat/Transact/InProgress.swift
index bb006162..81e4c8af 100644
--- a/sdks/swift/Mentat/Mentat/Transact/InProgress.swift
+++ b/sdks/swift/Mentat/Mentat/Transact/InProgress.swift
@@ -126,7 +126,10 @@ open class InProgress: OptionalRustObject {
defer {
self.raw = nil
}
- return EntityBuilder(raw: in_progress_entity_builder_from_temp_id(try self.validPointer(), tempId))
+ let builder = try RustError.unwrap({ err in
+ in_progress_entity_builder_from_temp_id(try self.validPointer(), tempId, err)
+ })
+ return EntityBuilder(raw: builder)
}
/**
@@ -144,8 +147,10 @@ open class InProgress: OptionalRustObject {
- Returns: The `TxReport` generated by the transact.
*/
open func transact(transaction: String) throws -> TxReport {
- let result = in_progress_transact(try self.validPointer(), transaction).pointee
- return TxReport(raw: try result.unwrap())
+ let report = try RustError.unwrap({ err in
+ in_progress_transact(try self.validPointer(), transaction, err)
+ })
+ return TxReport(raw: report)
}
/**
@@ -160,7 +165,9 @@ open class InProgress: OptionalRustObject {
defer {
self.raw = nil
}
- try in_progress_commit(try self.validPointer()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_commit(try self.validPointer(), err)
+ })
}
/**
@@ -175,7 +182,9 @@ open class InProgress: OptionalRustObject {
defer {
self.raw = nil
}
- try in_progress_rollback(try self.validPointer()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_rollback(try self.validPointer(), err)
+ })
}
override open func cleanup(pointer: OpaquePointer) {
diff --git a/sdks/swift/Mentat/Mentat/Transact/InProgressBuilder.swift b/sdks/swift/Mentat/Mentat/Transact/InProgressBuilder.swift
index 8a4ce085..04c4c6c1 100644
--- a/sdks/swift/Mentat/Mentat/Transact/InProgressBuilder.swift
+++ b/sdks/swift/Mentat/Mentat/Transact/InProgressBuilder.swift
@@ -73,7 +73,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/long`.
*/
open func add(entid: Entid, keyword: String, long value: Int64) throws {
- try in_progress_builder_add_long(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_long(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -89,7 +91,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/ref`.
*/
open func add(entid: Entid, keyword: String, reference value: Entid) throws {
- try in_progress_builder_add_ref(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_ref(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -105,7 +109,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/keyword`.
*/
open func add(entid: Entid, keyword: String, keyword value: String) throws {
- try in_progress_builder_add_keyword(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_keyword(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -121,7 +127,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/boolean`.
*/
open func add(entid: Entid, keyword: String, boolean value: Bool) throws {
- try in_progress_builder_add_boolean(try self.validPointer(), entid, keyword, value ? 1 : 0).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_boolean(try self.validPointer(), entid, keyword, value ? 1 : 0, err)
+ })
}
/**
@@ -137,7 +145,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/double`.
*/
open func add(entid: Entid, keyword: String, double value: Double) throws {
- try in_progress_builder_add_double(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_double(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -153,7 +163,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/instant`.
*/
open func add(entid: Entid, keyword: String, date value: Date) throws {
- try in_progress_builder_add_timestamp(try self.validPointer(), entid, keyword, value.toMicroseconds()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_timestamp(try self.validPointer(), entid, keyword, value.toMicroseconds(), err)
+ })
}
/**
@@ -169,7 +181,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/string`.
*/
open func add(entid: Entid, keyword: String, string value: String) throws {
- try in_progress_builder_add_string(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_string(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -187,7 +201,9 @@ open class InProgressBuilder: OptionalRustObject {
open func add(entid: Entid, keyword: String, uuid value: UUID) throws {
var rawUuid = value.uuid
let _ = try withUnsafePointer(to: &rawUuid) { uuidPtr in
- try in_progress_builder_add_uuid(try self.validPointer(), entid, keyword, uuidPtr).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_add_uuid(try self.validPointer(), entid, keyword, uuidPtr, err)
+ })
}
}
@@ -204,7 +220,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/long`.
*/
open func retract(entid: Entid, keyword: String, long value: Int64) throws {
- try in_progress_builder_retract_long(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_long(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -220,7 +238,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/ref`.
*/
open func retract(entid: Entid, keyword: String, reference value: Entid) throws {
- try in_progress_builder_retract_ref(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_ref(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -236,7 +256,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/keyword`.
*/
open func retract(entid: Entid, keyword: String, keyword value: String) throws {
- try in_progress_builder_retract_keyword(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_keyword(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -252,7 +274,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/boolean`.
*/
open func retract(entid: Entid, keyword: String, boolean value: Bool) throws {
- try in_progress_builder_retract_boolean(try self.validPointer(), entid, keyword, value ? 1 : 0).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_boolean(try self.validPointer(), entid, keyword, value ? 1 : 0, err)
+ })
}
/**
@@ -268,7 +292,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/double`.
*/
open func retract(entid: Entid, keyword: String, double value: Double) throws {
- try in_progress_builder_retract_double(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_double(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -284,7 +310,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/instant`.
*/
open func retract(entid: Entid, keyword: String, date value: Date) throws {
- try in_progress_builder_retract_timestamp(try self.validPointer(), entid, keyword, value.toMicroseconds()).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_timestamp(try self.validPointer(), entid, keyword, value.toMicroseconds(), err)
+ })
}
/**
@@ -300,7 +328,9 @@ open class InProgressBuilder: OptionalRustObject {
is not `:db.type/string`.
*/
open func retract(entid: Entid, keyword: String, string value: String) throws {
- try in_progress_builder_retract_string(try self.validPointer(), entid, keyword, value).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_string(try self.validPointer(), entid, keyword, value, err)
+ })
}
/**
@@ -318,7 +348,9 @@ open class InProgressBuilder: OptionalRustObject {
open func retract(entid: Entid, keyword: String, uuid value: UUID) throws {
var rawUuid = value.uuid
let _ = try withUnsafePointer(to: &rawUuid) { uuidPtr in
- try in_progress_builder_retract_uuid(try self.validPointer(), entid, keyword, uuidPtr).pointee.tryUnwrap()
+ try RustError.withErrorCheck({ err in
+ in_progress_builder_retract_uuid(try self.validPointer(), entid, keyword, uuidPtr, err)
+ })
}
}
@@ -340,9 +372,12 @@ open class InProgressBuilder: OptionalRustObject {
defer {
self.raw = nil
}
- let result = in_progress_builder_transact(try self.validPointer()).pointee
- let inProgress = InProgress(raw: result.inProgress)
- guard let report = try result.result.pointee.tryUnwrap() else {
+ let result = in_progress_builder_transact(try self.validPointer())
+ if let errorMessage = result.error.message {
+ throw ResultError.error(message: String(destroyingRustString: errorMessage))
+ }
+ let inProgress = InProgress(raw: result.inProgress);
+ guard let report = result.txReport else {
return (inProgress, nil)
}
return (inProgress, TxReport(raw: report))
@@ -363,7 +398,9 @@ open class InProgressBuilder: OptionalRustObject {
defer {
self.raw = nil
}
- return TxReport(raw: try in_progress_builder_commit(try self.validPointer()).pointee.unwrap())
+ return TxReport(raw: try RustError.unwrap({err in
+ in_progress_builder_commit(try self.validPointer(), err)
+ }));
}
override open func cleanup(pointer: OpaquePointer) {
diff --git a/sdks/swift/Mentat/Mentat/Transact/TxReport.swift b/sdks/swift/Mentat/Mentat/Transact/TxReport.swift
index 841be07b..fa0ed121 100644
--- a/sdks/swift/Mentat/Mentat/Transact/TxReport.swift
+++ b/sdks/swift/Mentat/Mentat/Transact/TxReport.swift
@@ -52,7 +52,9 @@ open class TxReport: RustObject {
guard let entidPtr = tx_report_entity_for_temp_id(self.raw, tempId) else {
return nil
}
- return entidPtr.pointee
+ let entid = entidPtr.pointee;
+ destroy(entidPtr);
+ return entid
}
override open func cleanup(pointer: OpaquePointer) {
diff --git a/sdks/swift/Mentat/Mentat/store.h b/sdks/swift/Mentat/Mentat/store.h
index e8ae9af9..4163358b 100644
--- a/sdks/swift/Mentat/Mentat/store.h
+++ b/sdks/swift/Mentat/Mentat/store.h
@@ -21,52 +21,69 @@
* macros and flags that will not be recognised by other C based languages.
*/
+
+// Opaque Structs mapping to Rust types that are passed over the FFI boundary. In cases where the
+// struct's name differs from the name used for the Rust type, it's noted in a comment.
+struct EntityBuilder; // Note: a `mentat::EntityBuilder>`
+struct InProgress;
+struct InProgressBuilder;
+struct Query; // Note: a `mentat::QueryBuilder`
+struct QueryResultRow; // Note: a `Vec`
+struct QueryResultRows; // Note: a `mentat::RelResult`
+struct QueryRowsIterator; // Note: a `mentat::BindingListIterator`
+struct QueryRowIterator; // Note: a `mentat::BindingIterator`
+struct Store;
+struct TxReport;
+struct TypedValue; // Note: a `mentat::Binding`
+
+
/*
- A mapping of the TxChange repr(C) Rust object.
- The memory for this is managed by Swift.
+ A mapping of the TransactionChange repr(C) Rust object.
+ The memory for this is managed by Rust.
*/
struct TxChange {
int64_t txid;
- int64_t*_Nonnull* _Nonnull changes;
+ const int64_t* _Nonnull changes;
uint64_t len;
};
/*
A mapping of the TxChangeList repr(C) Rust object.
- The memory for this is managed by Swift.
+ The memory for this is managed by Rust.
*/
struct TxChangeList {
- struct TxChange*_Nonnull* _Nonnull reports;
+ const struct TxChange* _Nonnull reports;
uint64_t len;
};
typedef struct TxChangeList TxChangeList;
-/*
- A mapping of the ExternResult repr(C) Rust object.
- The memory for this is managed by Swift.
- */
-struct Result {
- void* _Nullable ok;
- char* _Nullable err;
+/* Representation of the `ExternError` Rust type.
+
+ If `message` is not null, an error occur occurred (and we're responsible for freeing `message`,
+ using `rust_c_string_destroy`).
+*/
+struct RustError {
+ char *message;
};
-typedef struct Result Result;
/*
- A mapping of the ExternOption repr(C) Rust object.
- The memory for this is managed by Swift.
+ A mapping of the ExternResult<()> repr(C) Rust object.
+ These are not allocated on the heap, but the memory for `ok` and `err`
+ is managed by Swift.
*/
-struct Option {
- void* _Nullable value;
-};
-typedef struct Option Option;
+struct VoidResult { void* _Nullable ok; char* _Nullable err; };
+#define DEFINE_RESULT(Name, Type) struct Name { struct Type *_Nullable ok; char *_Nullable err; }
/*
A mapping of the InProgressTransactResult repr(C) Rust object.
- The memory for this is managed by Swift.
+ These are not allocated on the heap, but the memory for `inProgress`,
+ `txReport`, and `result.message` (if pressent)
+ as well as `result.ok` and `result.err`, are managed by Swift.
*/
struct InProgressTransactResult {
- struct InProgress*_Nonnull inProgress;
- struct Result*_Nonnull result;
+ struct InProgress *_Nonnull inProgress;
+ struct TxReport *_Nullable txReport;
+ struct RustError error;
};
typedef struct InProgressTransactResult InProgressTransactResult;
@@ -84,24 +101,12 @@ typedef NS_ENUM(NSInteger, ValueType) {
ValueTypeUuid
};
-// Opaque Structs mapping to Rust types that are passed over the FFI boundary
-struct EntityBuilder;
-struct InProgress;
-struct InProgressBuilder;
-struct Query;
-struct QueryResultRow;
-struct QueryResultRows;
-struct QueryRowsIterator;
-struct QueryRowIterator;
-struct Store;
-struct TxReport;
-struct TypedValue;
-
// Store
struct Store*_Nonnull store_open(const char*_Nonnull uri);
// Destructors.
void destroy(void* _Nullable obj);
+void uuid_destroy(uuid_t* _Nullable obj);
void query_builder_destroy(struct Query* _Nullable obj);
void store_destroy(struct Store* _Nonnull obj);
void tx_report_destroy(struct TxReport* _Nonnull obj);
@@ -113,72 +118,73 @@ void typed_value_result_set_iter_destroy(struct QueryRowsIterator* _Nullable obj
void in_progress_destroy(struct InProgress* _Nullable obj);
void in_progress_builder_destroy(struct InProgressBuilder* _Nullable obj);
void entity_builder_destroy(struct EntityBuilder* _Nullable obj);
-
+void rust_c_string_destroy(char *_Nullable s);
// caching
-struct Result*_Nonnull store_cache_attribute_forward(struct Store*_Nonnull store, const char* _Nonnull attribute);
-struct Result*_Nonnull store_cache_attribute_reverse(struct Store*_Nonnull store, const char* _Nonnull attribute);
-struct Result*_Nonnull store_cache_attribute_bi_directional(struct Store*_Nonnull store, const char* _Nonnull attribute);
+void store_cache_attribute_forward(struct Store*_Nonnull store, const char* _Nonnull attribute, struct RustError* _Nonnull error);
+void store_cache_attribute_reverse(struct Store*_Nonnull store, const char* _Nonnull attribute, struct RustError* _Nonnull error);
+void store_cache_attribute_bi_directional(struct Store*_Nonnull store, const char* _Nonnull attribute, struct RustError* _Nonnull error);
// transact
-struct Result*_Nonnull store_transact(struct Store*_Nonnull store, const char* _Nonnull transaction);
-const int64_t* _Nullable tx_report_entity_for_temp_id(const struct TxReport* _Nonnull report, const char* _Nonnull tempid);
-int64_t tx_report_get_entid(const struct TxReport* _Nonnull report);
+struct TxReport*_Nullable store_transact(struct Store*_Nonnull store, const char* _Nonnull transaction, struct RustError* _Nonnull error);
+int64_t* _Nullable tx_report_entity_for_temp_id(const struct TxReport* _Nonnull report, const char* _Nonnull tempid);
+int64_t tx_report_get_entid(const struct TxReport* _Nonnull report);
int64_t tx_report_get_tx_instant(const struct TxReport* _Nonnull report);
-struct Result*_Nonnull store_begin_transaction(struct Store*_Nonnull store);
+struct InProgress *_Nullable store_begin_transaction(struct Store*_Nonnull store, struct RustError* _Nonnull error);
// in progress
-struct Result*_Nonnull in_progress_transact(struct InProgress*_Nonnull in_progress, const char* _Nonnull transaction);
-struct Result*_Nonnull in_progress_commit(struct InProgress*_Nonnull in_progress);
-struct Result*_Nonnull in_progress_rollback(struct InProgress*_Nonnull in_progress);
+struct TxReport*_Nullable in_progress_transact(struct InProgress*_Nonnull in_progress, const char* _Nonnull transaction, struct RustError*_Nonnull err);
+void in_progress_commit(struct InProgress*_Nonnull in_progress, struct RustError* _Nonnull error);
+void in_progress_rollback(struct InProgress*_Nonnull in_progress, struct RustError* _Nonnull error);
// in_progress entity building
-struct Result*_Nonnull store_in_progress_builder(struct Store*_Nonnull store);
+struct InProgressBuilder*_Nullable store_in_progress_builder(struct Store*_Nonnull store, struct RustError* _Nonnull error);
struct InProgressBuilder*_Nonnull in_progress_builder(struct InProgress*_Nonnull in_progress);
-struct EntityBuilder*_Nonnull in_progress_entity_builder_from_temp_id(struct InProgress*_Nonnull in_progress, const char*_Nonnull temp_id);
+
+struct EntityBuilder*_Nonnull in_progress_entity_builder_from_temp_id(struct InProgress*_Nonnull in_progress, const char*_Nonnull temp_id, struct RustError* _Nonnull error);
struct EntityBuilder*_Nonnull in_progress_entity_builder_from_entid(struct InProgress*_Nonnull in_progress, const int64_t entid);
-struct Result*_Nonnull in_progress_builder_add_string(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull in_progress_builder_add_long(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_add_ref(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_add_keyword(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull in_progress_builder_add_timestamp(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_add_boolean(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int32_t value);
-struct Result*_Nonnull in_progress_builder_add_double(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const double value);
-struct Result*_Nonnull in_progress_builder_add_uuid(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const uuid_t* _Nonnull value);
-struct Result*_Nonnull in_progress_builder_retract_string(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull in_progress_builder_retract_long(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_retract_ref(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_retract_keyword(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull in_progress_builder_retract_timestamp(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull in_progress_builder_retract_boolean(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int32_t value);
-struct Result*_Nonnull in_progress_builder_retract_double(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const double value);
-struct Result*_Nonnull in_progress_builder_retract_uuid(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const uuid_t* _Nonnull value);
-struct InProgressTransactResult*_Nonnull in_progress_builder_transact(struct InProgressBuilder*_Nonnull builder);
-struct Result*_Nonnull in_progress_builder_commit(struct InProgressBuilder*_Nonnull builder);
+
+void in_progress_builder_add_string(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void in_progress_builder_add_long(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_add_ref(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_add_keyword(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void in_progress_builder_add_timestamp(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_add_boolean(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int32_t value, struct RustError* _Nonnull error);
+void in_progress_builder_add_double(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const double value, struct RustError* _Nonnull error);
+void in_progress_builder_add_uuid(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const uuid_t* _Nonnull value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_string(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_long(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_ref(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_keyword(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_timestamp(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_boolean(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const int32_t value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_double(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const double value, struct RustError* _Nonnull error);
+void in_progress_builder_retract_uuid(struct InProgressBuilder*_Nonnull builder, const int64_t entid, const char*_Nonnull kw, const uuid_t* _Nonnull value, struct RustError* _Nonnull error);
+struct InProgressTransactResult in_progress_builder_transact(struct InProgressBuilder*_Nonnull builder);
+struct TxReport*_Nullable in_progress_builder_commit(struct InProgressBuilder*_Nonnull builder, struct RustError* _Nonnull error);
// entity building
-struct Result*_Nonnull store_entity_builder_from_temp_id(struct Store*_Nonnull store, const char*_Nonnull temp_id);
-struct Result*_Nonnull store_entity_builder_from_entid(struct Store*_Nonnull store, const int64_t entid);
-struct Result*_Nonnull entity_builder_add_string(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull entity_builder_add_long(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_add_ref(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_add_keyword(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull entity_builder_add_boolean(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int32_t value);
-struct Result*_Nonnull entity_builder_add_double(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const double value);
-struct Result*_Nonnull entity_builder_add_timestamp(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_add_uuid(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const uuid_t* _Nonnull value);
-struct Result*_Nonnull entity_builder_retract_string(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull entity_builder_retract_long(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_retract_ref(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_retract_keyword(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value);
-struct Result*_Nonnull entity_builder_retract_boolean(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int32_t value);
-struct Result*_Nonnull entity_builder_retract_double(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const double value);
-struct Result*_Nonnull entity_builder_retract_timestamp(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value);
-struct Result*_Nonnull entity_builder_retract_uuid(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const uuid_t* _Nonnull value);
-struct InProgressTransactResult*_Nonnull entity_builder_transact(struct InProgressBuilder*_Nonnull builder);
-struct Result*_Nonnull entity_builder_commit(struct EntityBuilder*_Nonnull builder);
+struct EntityBuilder*_Nullable store_entity_builder_from_temp_id(struct Store*_Nonnull store, const char*_Nonnull temp_id, struct RustError* _Nonnull error);
+struct EntityBuilder*_Nullable store_entity_builder_from_entid(struct Store*_Nonnull store, const int64_t entid, struct RustError* _Nonnull error) ;
+void entity_builder_add_string(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void entity_builder_add_long(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_add_ref(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_add_keyword(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void entity_builder_add_boolean(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int32_t value, struct RustError* _Nonnull error);
+void entity_builder_add_double(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const double value, struct RustError* _Nonnull error);
+void entity_builder_add_timestamp(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_add_uuid(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const uuid_t* _Nonnull value, struct RustError* _Nonnull error);
-// Sync
-struct Result*_Nonnull store_sync(struct Store*_Nonnull store, const char* _Nonnull user_uuid, const char* _Nonnull server_uri);
+void entity_builder_retract_string(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void entity_builder_retract_long(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_retract_ref(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_retract_keyword(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const char*_Nonnull value, struct RustError* _Nonnull error);
+void entity_builder_retract_boolean(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int32_t value, struct RustError* _Nonnull error);
+void entity_builder_retract_double(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const double value, struct RustError* _Nonnull error);
+void entity_builder_retract_timestamp(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const int64_t value, struct RustError* _Nonnull error);
+void entity_builder_retract_uuid(struct EntityBuilder*_Nonnull builder, const char*_Nonnull kw, const uuid_t* _Nonnull value, struct RustError* _Nonnull error);
+
+struct InProgressTransactResult entity_builder_transact(struct EntityBuilder*_Nonnull builder);
+struct TxReport*_Nullable entity_builder_commit(struct EntityBuilder*_Nonnull builder, struct RustError* _Nonnull error);
// Observers
void store_register_observer(struct Store*_Nonnull store, const char* _Nonnull key, const int64_t* _Nonnull attributes, const int64_t len, void (*_Nonnull callback_fn)(const char* _Nonnull key, const struct TxChangeList* _Nonnull reports));
@@ -188,7 +194,7 @@ int64_t changelist_entry_at(const struct TxChange* _Nonnull report, size_t index
// Query
struct Query*_Nonnull store_query(struct Store*_Nonnull store, const char* _Nonnull query);
-struct Result*_Nonnull store_value_for_attribute(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute);
+struct TypedValue*_Nullable store_value_for_attribute(struct Store*_Nonnull store, const int64_t entid, const char* _Nonnull attribute, struct RustError* _Nonnull error);
// Query Variable Binding
void query_builder_bind_long(struct Query*_Nonnull query, const char* _Nonnull var, const int64_t value);
@@ -202,20 +208,20 @@ void query_builder_bind_string(struct Query*_Nonnull query, const char* _Nonnull
void query_builder_bind_uuid(struct Query*_Nonnull query, const char* _Nonnull var, const uuid_t* _Nonnull value);
// Query execution
-struct Result*_Nonnull query_builder_execute(struct Query*_Nonnull query);
-struct Result*_Nonnull query_builder_execute_scalar(struct Query*_Nonnull query);
-struct Result*_Nonnull query_builder_execute_coll(struct Query*_Nonnull query);
-struct Result*_Nonnull query_builder_execute_tuple(struct Query*_Nonnull query);
+struct QueryResultRows* _Nullable query_builder_execute(struct Query*_Nonnull query, struct RustError* _Nonnull error);
+struct TypedValue* _Nullable query_builder_execute_scalar(struct Query*_Nonnull query, struct RustError* _Nonnull error);
+struct QueryResultRow* _Nullable query_builder_execute_coll(struct Query*_Nonnull query, struct RustError* _Nonnull error);
+struct QueryResultRow* _Nullable query_builder_execute_tuple(struct Query*_Nonnull query, struct RustError* _Nonnull error);
// Query Result Processing
int64_t typed_value_into_long(struct TypedValue*_Nonnull value);
int64_t typed_value_into_entid(struct TypedValue*_Nonnull value);
-const char* _Nonnull typed_value_into_kw(struct TypedValue*_Nonnull value);
+char* _Nonnull typed_value_into_kw(struct TypedValue*_Nonnull value);
int32_t typed_value_into_boolean(struct TypedValue*_Nonnull value);
double typed_value_into_double(struct TypedValue*_Nonnull value);
int64_t typed_value_into_timestamp(struct TypedValue*_Nonnull value);
-const char* _Nonnull typed_value_into_string(struct TypedValue*_Nonnull value);
-const uuid_t* _Nonnull typed_value_into_uuid(struct TypedValue*_Nonnull value);
+char* _Nonnull typed_value_into_string(struct TypedValue*_Nonnull value);
+uuid_t* _Nonnull typed_value_into_uuid(struct TypedValue*_Nonnull value);
enum ValueType typed_value_value_type(struct TypedValue*_Nonnull value);
struct QueryResultRow* _Nullable row_at_index(struct QueryResultRows* _Nonnull rows, const int32_t index);
@@ -227,14 +233,15 @@ struct TypedValue* _Nullable typed_value_list_iter_next(struct QueryRowIterator*
struct TypedValue* _Nonnull value_at_index(struct QueryResultRow* _Nonnull row, const int32_t index);
int64_t value_at_index_into_long(struct QueryResultRow* _Nonnull row, const int32_t index);
int64_t value_at_index_into_entid(struct QueryResultRow* _Nonnull row, const int32_t index);
-const char* _Nonnull value_at_index_into_kw(struct QueryResultRow* _Nonnull row, const int32_t index);
+char* _Nonnull value_at_index_into_kw(struct QueryResultRow* _Nonnull row, const int32_t index);
int32_t value_at_index_into_boolean(struct QueryResultRow* _Nonnull row, const int32_t index);
double value_at_index_into_double(struct QueryResultRow* _Nonnull row, const int32_t index);
int64_t value_at_index_into_timestamp(struct QueryResultRow* _Nonnull row, const int32_t index);
-const char* _Nonnull value_at_index_into_string(struct QueryResultRow* _Nonnull row, const int32_t index);
-const uuid_t* _Nonnull value_at_index_into_uuid(struct QueryResultRow* _Nonnull row, const int32_t index);
+char* _Nonnull value_at_index_into_string(struct QueryResultRow* _Nonnull row, const int32_t index);
+uuid_t* _Nonnull value_at_index_into_uuid(struct QueryResultRow* _Nonnull row, const int32_t index);
// Transaction change lists
-const struct TxChange* _Nullable tx_change_list_entry_at(const struct TxChangeList* _Nonnull list, size_t index);
+const struct TxChange* _Nonnull tx_change_list_entry_at(const struct TxChangeList* _Nonnull list, size_t index);
#endif /* store_h */
+