simplify TCResult to just two values

This commit is contained in:
Dustin J. Mitchell 2022-02-01 00:46:04 +00:00
parent b675cef99c
commit 22a6857c1b
6 changed files with 77 additions and 61 deletions

View file

@ -23,8 +23,20 @@ static void test_replica_creation_disk(void) {
static void test_replica_undo_empty(void) { static void test_replica_undo_empty(void) {
TCReplica *rep = tc_replica_new_in_memory(); TCReplica *rep = tc_replica_new_in_memory();
TEST_ASSERT_NULL(tc_replica_error(rep)); TEST_ASSERT_NULL(tc_replica_error(rep));
int rv = tc_replica_undo(rep); int undone;
TEST_ASSERT_EQUAL(TC_RESULT_FALSE, rv); int rv = tc_replica_undo(rep, &undone);
TEST_ASSERT_EQUAL(TC_RESULT_OK, rv);
TEST_ASSERT_EQUAL(0, undone);
TEST_ASSERT_NULL(tc_replica_error(rep));
tc_replica_free(rep);
}
// When tc_replica_undo is passed NULL for undone_out, it still succeeds
static void test_replica_undo_empty_null_undone_out(void) {
TCReplica *rep = tc_replica_new_in_memory();
TEST_ASSERT_NULL(tc_replica_error(rep));
int rv = tc_replica_undo(rep, NULL);
TEST_ASSERT_EQUAL(TC_RESULT_OK, rv);
TEST_ASSERT_NULL(tc_replica_error(rep)); TEST_ASSERT_NULL(tc_replica_error(rep));
tc_replica_free(rep); tc_replica_free(rep);
} }
@ -110,6 +122,7 @@ int replica_tests(void) {
RUN_TEST(test_replica_creation); RUN_TEST(test_replica_creation);
RUN_TEST(test_replica_creation_disk); RUN_TEST(test_replica_creation_disk);
RUN_TEST(test_replica_undo_empty); RUN_TEST(test_replica_undo_empty);
RUN_TEST(test_replica_undo_empty_null_undone_out);
RUN_TEST(test_replica_task_creation); RUN_TEST(test_replica_task_creation);
RUN_TEST(test_replica_task_import); RUN_TEST(test_replica_task_import);
RUN_TEST(test_replica_get_task_not_found); RUN_TEST(test_replica_get_task_not_found);

View file

@ -41,7 +41,7 @@ static void test_task_free_mutable_task(void) {
TCUuid uuid = tc_task_get_uuid(task); TCUuid uuid = tc_task_get_uuid(task);
tc_task_to_mut(task, rep); tc_task_to_mut(task, rep);
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_status(task, TC_STATUS_DELETED)); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_set_status(task, TC_STATUS_DELETED));
TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task));
tc_task_free(task); // implicitly converts to immut tc_task_free(task); // implicitly converts to immut
@ -68,7 +68,7 @@ static void test_task_get_set_status(void) {
TEST_ASSERT_EQUAL(TC_STATUS_PENDING, tc_task_get_status(task)); TEST_ASSERT_EQUAL(TC_STATUS_PENDING, tc_task_get_status(task));
tc_task_to_mut(task, rep); tc_task_to_mut(task, rep);
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_status(task, TC_STATUS_DELETED)); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_set_status(task, TC_STATUS_DELETED));
TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); // while mut TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); // while mut
tc_task_to_immut(task); tc_task_to_immut(task);
TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); // while immut TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); // while immut
@ -92,7 +92,7 @@ static void test_task_get_set_description(void) {
TCString *desc; TCString *desc;
tc_task_to_mut(task, rep); tc_task_to_mut(task, rep);
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_description(task, tc_string_borrow("updated"))); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_set_description(task, tc_string_borrow("updated")));
TEST_ASSERT_TRUE(desc = tc_task_get_description(task)); TEST_ASSERT_TRUE(desc = tc_task_get_description(task));
TEST_ASSERT_NOT_NULL(desc); TEST_ASSERT_NOT_NULL(desc);
@ -127,9 +127,9 @@ static void test_task_start_stop_is_active(void) {
tc_task_to_mut(task, rep); tc_task_to_mut(task, rep);
TEST_ASSERT_FALSE(tc_task_is_active(task)); TEST_ASSERT_FALSE(tc_task_is_active(task));
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_start(task)); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_start(task));
TEST_ASSERT_TRUE(tc_task_is_active(task)); TEST_ASSERT_TRUE(tc_task_is_active(task));
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_stop(task)); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_stop(task));
TEST_ASSERT_FALSE(tc_task_is_active(task)); TEST_ASSERT_FALSE(tc_task_is_active(task));
tc_task_free(task); tc_task_free(task);
@ -149,7 +149,7 @@ static void task_task_add_tag(void) {
tc_task_to_mut(task, rep); tc_task_to_mut(task, rep);
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_add_tag(task, tc_string_borrow("next"))); TEST_ASSERT_EQUAL(TC_RESULT_OK, tc_task_add_tag(task, tc_string_borrow("next")));
TEST_ASSERT_NULL(tc_task_error(task)); TEST_ASSERT_NULL(tc_task_error(task));
// invalid - synthetic tag // invalid - synthetic tag

View file

@ -6,6 +6,9 @@ use taskchampion::{Replica, StorageConfig, Uuid};
/// for querying and modifying that data. /// for querying and modifying that data.
/// ///
/// TCReplicas are not threadsafe. /// TCReplicas are not threadsafe.
///
/// When a `tc_replica_..` function that returns a TCResult returns TC_RESULT_ERROR, then
/// `tc_replica_error` will return the error message.
pub struct TCReplica { pub struct TCReplica {
/// The wrapped Replica /// The wrapped Replica
inner: Replica, inner: Replica,
@ -213,18 +216,21 @@ pub extern "C" fn tc_replica_import_task_with_uuid(
/// Undo local operations until the most recent UndoPoint. /// Undo local operations until the most recent UndoPoint.
/// ///
/// Returns TC_RESULT_TRUE if an undo occurred, TC_RESULT_FALSE if there are no operations /// If undone_out is not NULL, then on success it is set to 1 if operations were undone, or 0 if
/// to be undone, or TC_RESULT_ERROR on error. /// there are no operations that can be done.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_replica_undo<'a>(rep: *mut TCReplica) -> TCResult { pub extern "C" fn tc_replica_undo<'a>(rep: *mut TCReplica, undone_out: *mut i32) -> TCResult {
wrap( wrap(
rep, rep,
|rep| { |rep| {
Ok(if rep.undo()? { let undone = if rep.undo()? { 1 } else { 0 };
TCResult::True if !undone_out.is_null() {
} else { // SAFETY:
TCResult::False // - undone_out is not NULL (just checked)
}) // - undone_out is properly aligned (implicitly promised by caller)
unsafe { *undone_out = undone };
}
Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )

View file

@ -1,11 +1,9 @@
// TODO: make true = 1, false = 0, error = -1 /// A result from a TC operation. Typically if this value is TC_RESULT_ERROR,
/// A result combines a boolean success value with /// the associated object's `tc_.._error` method will return an error message.
/// an error response. It is equivalent to `Result<bool, ()>`.
/// cbindgen:prefix-with-name /// cbindgen:prefix-with-name
/// cbindgen:rename-all=ScreamingSnakeCase /// cbindgen:rename-all=ScreamingSnakeCase
#[repr(C)] #[repr(i32)]
pub enum TCResult { pub enum TCResult {
Error = -1, Error = -1,
False = 0, Ok = 0,
True = 1,
} }

View file

@ -16,6 +16,11 @@ use taskchampion::{Tag, Task, TaskMut};
/// be used until it is freed or converted to a TaskMut. /// be used until it is freed or converted to a TaskMut.
/// ///
/// All `tc_task_..` functions taking a task as an argument require that it not be NULL. /// All `tc_task_..` functions taking a task as an argument require that it not be NULL.
///
/// When a `tc_task_..` function that returns a TCResult returns TC_RESULT_ERROR, then
/// `tc_task_error` will return the error message.
///
/// TCTasks are not threadsafe.
pub struct TCTask { pub struct TCTask {
/// The wrapped Task or TaskMut /// The wrapped Task or TaskMut
inner: Inner, inner: Inner,
@ -249,23 +254,19 @@ pub extern "C" fn tc_task_is_active<'a>(task: *mut TCTask) -> bool {
// TODO: tc_task_get_modified // TODO: tc_task_get_modified
/// Set a mutable task's status. /// Set a mutable task's status.
///
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_task_set_status<'a>(task: *mut TCTask, status: TCStatus) -> TCResult { pub extern "C" fn tc_task_set_status<'a>(task: *mut TCTask, status: TCStatus) -> TCResult {
wrap_mut( wrap_mut(
task, task,
|task| { |task| {
task.set_status(status.into())?; task.set_status(status.into())?;
Ok(TCResult::True) Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )
} }
/// Set a mutable task's description. /// Set a mutable task's description.
///
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_task_set_description<'a>( pub extern "C" fn tc_task_set_description<'a>(
task: *mut TCTask, task: *mut TCTask,
@ -279,7 +280,7 @@ pub extern "C" fn tc_task_set_description<'a>(
task, task,
|task| { |task| {
task.set_description(description.as_str()?.to_string())?; task.set_description(description.as_str()?.to_string())?;
Ok(TCResult::True) Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )
@ -290,30 +291,26 @@ pub extern "C" fn tc_task_set_description<'a>(
// TODO: tc_task_set_modified // TODO: tc_task_set_modified
/// Start a task. /// Start a task.
///
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_task_start<'a>(task: *mut TCTask) -> TCResult { pub extern "C" fn tc_task_start<'a>(task: *mut TCTask) -> TCResult {
wrap_mut( wrap_mut(
task, task,
|task| { |task| {
task.start()?; task.start()?;
Ok(TCResult::True) Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )
} }
/// Stop a task. /// Stop a task.
///
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) -> TCResult { pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) -> TCResult {
wrap_mut( wrap_mut(
task, task,
|task| { |task| {
task.stop()?; task.stop()?;
Ok(TCResult::True) Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )
@ -323,8 +320,6 @@ pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) -> TCResult {
// TODO: tc_task_delete // TODO: tc_task_delete
/// Add a tag to a mutable task. /// Add a tag to a mutable task.
///
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_task_add_tag<'a>(task: *mut TCTask, tag: *mut TCString) -> TCResult { pub extern "C" fn tc_task_add_tag<'a>(task: *mut TCTask, tag: *mut TCString) -> TCResult {
// SAFETY: // SAFETY:
@ -337,7 +332,7 @@ pub extern "C" fn tc_task_add_tag<'a>(task: *mut TCTask, tag: *mut TCString) ->
let tagstr = tcstring.as_str()?; let tagstr = tcstring.as_str()?;
let tag = Tag::from_str(tagstr)?; let tag = Tag::from_str(tagstr)?;
task.add_tag(&tag)?; task.add_tag(&tag)?;
Ok(TCResult::True) Ok(TCResult::Ok)
}, },
TCResult::Error, TCResult::Error,
) )

View file

@ -7,14 +7,20 @@
#define TC_UUID_STRING_BYTES 36 #define TC_UUID_STRING_BYTES 36
/** /**
* A result combines a boolean success value with * A result from a TC operation. Typically if this value is TC_RESULT_ERROR,
* an error response. It is equivalent to `Result<bool, ()>`. * the associated object's `tc_.._error` method will return an error message.
*/ */
typedef enum TCResult { enum TCResult
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
TC_RESULT_ERROR = -1, TC_RESULT_ERROR = -1,
TC_RESULT_FALSE = 0, TC_RESULT_OK = 0,
TC_RESULT_TRUE = 1, };
} TCResult; #ifndef __cplusplus
typedef int32_t TCResult;
#endif // __cplusplus
/** /**
* The status of a task, as defined by the task data model. * The status of a task, as defined by the task data model.
@ -35,6 +41,9 @@ typedef enum TCStatus {
* for querying and modifying that data. * for querying and modifying that data.
* *
* TCReplicas are not threadsafe. * TCReplicas are not threadsafe.
*
* When a `tc_replica_..` function that returns a TCResult returns TC_RESULT_ERROR, then
* `tc_replica_error` will return the error message.
*/ */
typedef struct TCReplica TCReplica; typedef struct TCReplica TCReplica;
@ -69,6 +78,11 @@ typedef struct TCString TCString;
* be used until it is freed or converted to a TaskMut. * be used until it is freed or converted to a TaskMut.
* *
* All `tc_task_..` functions taking a task as an argument require that it not be NULL. * All `tc_task_..` functions taking a task as an argument require that it not be NULL.
*
* When a `tc_task_..` function that returns a TCResult returns TC_RESULT_ERROR, then
* `tc_task_error` will return the error message.
*
* TCTasks are not threadsafe.
*/ */
typedef struct TCTask TCTask; typedef struct TCTask TCTask;
@ -127,10 +141,10 @@ struct TCTask *tc_replica_import_task_with_uuid(struct TCReplica *rep, struct TC
/** /**
* Undo local operations until the most recent UndoPoint. * Undo local operations until the most recent UndoPoint.
* *
* Returns TC_RESULT_TRUE if an undo occurred, TC_RESULT_FALSE if there are no operations * If undone_out is not NULL, then on success it is set to 1 if operations were undone, or 0 if
* to be undone, or TC_RESULT_ERROR on error. * there are no operations that can be done.
*/ */
enum TCResult tc_replica_undo(struct TCReplica *rep); TCResult tc_replica_undo(struct TCReplica *rep, int32_t *undone_out);
/** /**
* Get the latest error for a replica, or NULL if the last operation succeeded. Subsequent calls * Get the latest error for a replica, or NULL if the last operation succeeded. Subsequent calls
@ -257,38 +271,28 @@ bool tc_task_is_active(struct TCTask *task);
/** /**
* Set a mutable task's status. * Set a mutable task's status.
*
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
*/ */
enum TCResult tc_task_set_status(struct TCTask *task, enum TCStatus status); TCResult tc_task_set_status(struct TCTask *task, enum TCStatus status);
/** /**
* Set a mutable task's description. * Set a mutable task's description.
*
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
*/ */
enum TCResult tc_task_set_description(struct TCTask *task, struct TCString *description); TCResult tc_task_set_description(struct TCTask *task, struct TCString *description);
/** /**
* Start a task. * Start a task.
*
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
*/ */
enum TCResult tc_task_start(struct TCTask *task); TCResult tc_task_start(struct TCTask *task);
/** /**
* Stop a task. * Stop a task.
*
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
*/ */
enum TCResult tc_task_stop(struct TCTask *task); TCResult tc_task_stop(struct TCTask *task);
/** /**
* Add a tag to a mutable task. * Add a tag to a mutable task.
*
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
*/ */
enum TCResult tc_task_add_tag(struct TCTask *task, struct TCString *tag); TCResult tc_task_add_tag(struct TCTask *task, struct TCString *tag);
/** /**
* Get the latest error for a task, or NULL if the last operation succeeded. Subsequent calls * Get the latest error for a task, or NULL if the last operation succeeded. Subsequent calls