mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
allow task setters to return error values
This commit is contained in:
parent
8bd9605b25
commit
ef0bb2ced4
4 changed files with 75 additions and 49 deletions
|
@ -41,7 +41,7 @@ static void test_task_free_mutable_task(void) {
|
|||
TCUuid uuid = tc_task_get_uuid(task);
|
||||
|
||||
tc_task_to_mut(task, rep);
|
||||
TEST_ASSERT_TRUE(tc_task_set_status(task, TC_STATUS_DELETED));
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_status(task, TC_STATUS_DELETED));
|
||||
TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task));
|
||||
|
||||
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));
|
||||
|
||||
tc_task_to_mut(task, rep);
|
||||
TEST_ASSERT_TRUE(tc_task_set_status(task, TC_STATUS_DELETED));
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_status(task, TC_STATUS_DELETED));
|
||||
TEST_ASSERT_EQUAL(TC_STATUS_DELETED, tc_task_get_status(task)); // while mut
|
||||
tc_task_to_immut(task);
|
||||
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;
|
||||
|
||||
tc_task_to_mut(task, rep);
|
||||
tc_task_set_description(task, tc_string_borrow("updated"));
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_set_description(task, tc_string_borrow("updated")));
|
||||
|
||||
TEST_ASSERT_TRUE(desc = tc_task_get_description(task));
|
||||
TEST_ASSERT_NOT_NULL(desc);
|
||||
|
@ -127,9 +127,9 @@ static void test_task_start_stop_is_active(void) {
|
|||
tc_task_to_mut(task, rep);
|
||||
|
||||
TEST_ASSERT_FALSE(tc_task_is_active(task));
|
||||
tc_task_start(task);
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_start(task));
|
||||
TEST_ASSERT_TRUE(tc_task_is_active(task));
|
||||
tc_task_stop(task);
|
||||
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_stop(task));
|
||||
TEST_ASSERT_FALSE(tc_task_is_active(task));
|
||||
|
||||
tc_task_free(task);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// TODO: make true = 1, false = 0, error = -1
|
||||
/// A result combines a boolean success value with
|
||||
/// an error response. It is equivalent to `Result<bool, ()>`.
|
||||
/// cbindgen:prefix-with-name
|
||||
/// cbindgen:rename-all=ScreamingSnakeCase
|
||||
#[repr(C)]
|
||||
pub enum TCResult {
|
||||
True,
|
||||
False,
|
||||
Error,
|
||||
Error = -1,
|
||||
False = 0,
|
||||
True = 1,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{replica::TCReplica, status::TCStatus, string::TCString, uuid::TCUuid};
|
||||
use crate::{
|
||||
replica::TCReplica, result::TCResult, status::TCStatus, string::TCString, uuid::TCUuid,
|
||||
};
|
||||
use std::ops::Deref;
|
||||
use taskchampion::{Task, TaskMut};
|
||||
|
||||
|
@ -113,7 +115,8 @@ impl From<Task> for TCTask {
|
|||
}
|
||||
}
|
||||
|
||||
/// Utility function to get a shared reference to the underlying Task.
|
||||
/// Utility function to get a shared reference to the underlying Task. All Task getters
|
||||
/// are error-free, so this does not handle errors.
|
||||
fn wrap<'a, T, F>(task: *const TCTask, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&Task) -> T,
|
||||
|
@ -131,8 +134,9 @@ where
|
|||
}
|
||||
|
||||
/// Utility function to get a mutable reference to the underlying Task. The
|
||||
/// TCTask must be mutable.
|
||||
fn wrap_mut<'a, T, F>(task: *mut TCTask, f: F) -> T
|
||||
/// TCTask must be mutable. The inner function may use `?` syntax to return an
|
||||
/// error, which will be represented with the `err_value` returned to C.
|
||||
fn wrap_mut<'a, T, F>(task: *mut TCTask, f: F, err_value: T) -> T
|
||||
where
|
||||
F: FnOnce(&mut TaskMut) -> anyhow::Result<T>,
|
||||
{
|
||||
|
@ -145,8 +149,13 @@ where
|
|||
TCTask::Mutable(ref mut t, _) => t,
|
||||
TCTask::Invalid => unreachable!(),
|
||||
};
|
||||
// TODO: add TCTask error handling, like replica
|
||||
f(task).unwrap()
|
||||
match f(task) {
|
||||
Ok(rv) => rv,
|
||||
Err(e) => {
|
||||
// TODO: add TCTask error handling, like replica
|
||||
err_value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an immutable task into a mutable task.
|
||||
|
@ -238,31 +247,39 @@ pub extern "C" fn tc_task_is_active<'a>(task: *const TCTask) -> bool {
|
|||
|
||||
/// Set a mutable task's status.
|
||||
///
|
||||
/// Returns false on error.
|
||||
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn tc_task_set_status<'a>(task: *mut TCTask, status: TCStatus) -> bool {
|
||||
wrap_mut(task, |task| {
|
||||
task.set_status(status.into())?;
|
||||
Ok(true)
|
||||
})
|
||||
pub extern "C" fn tc_task_set_status<'a>(task: *mut TCTask, status: TCStatus) -> TCResult {
|
||||
wrap_mut(
|
||||
task,
|
||||
|task| {
|
||||
task.set_status(status.into())?;
|
||||
Ok(TCResult::True)
|
||||
},
|
||||
TCResult::Error,
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a mutable task's description.
|
||||
///
|
||||
/// Returns false on error.
|
||||
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn tc_task_set_description<'a>(
|
||||
task: *mut TCTask,
|
||||
description: *mut TCString,
|
||||
) -> bool {
|
||||
) -> TCResult {
|
||||
// SAFETY:
|
||||
// - tcstring is not NULL (promised by caller)
|
||||
// - caller is exclusive owner of tcstring (implicitly promised by caller)
|
||||
let description = unsafe { TCString::from_arg(description) };
|
||||
wrap_mut(task, |task| {
|
||||
task.set_description(description.as_str()?.to_string())?;
|
||||
Ok(true)
|
||||
})
|
||||
wrap_mut(
|
||||
task,
|
||||
|task| {
|
||||
task.set_description(description.as_str()?.to_string())?;
|
||||
Ok(TCResult::True)
|
||||
},
|
||||
TCResult::Error,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: tc_task_set_description
|
||||
|
@ -272,24 +289,32 @@ pub extern "C" fn tc_task_set_description<'a>(
|
|||
|
||||
/// Start a task.
|
||||
///
|
||||
/// TODO: error
|
||||
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn tc_task_start<'a>(task: *mut TCTask) {
|
||||
wrap_mut(task, |task| {
|
||||
task.start()?;
|
||||
Ok(())
|
||||
})
|
||||
pub extern "C" fn tc_task_start<'a>(task: *mut TCTask) -> TCResult {
|
||||
wrap_mut(
|
||||
task,
|
||||
|task| {
|
||||
task.start()?;
|
||||
Ok(TCResult::True)
|
||||
},
|
||||
TCResult::Error,
|
||||
)
|
||||
}
|
||||
|
||||
/// Stop a task.
|
||||
///
|
||||
/// TODO: error
|
||||
/// Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) {
|
||||
wrap_mut(task, |task| {
|
||||
task.stop()?;
|
||||
Ok(())
|
||||
})
|
||||
pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) -> TCResult {
|
||||
wrap_mut(
|
||||
task,
|
||||
|task| {
|
||||
task.stop()?;
|
||||
Ok(TCResult::True)
|
||||
},
|
||||
TCResult::Error,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: tc_task_done
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
* an error response. It is equivalent to `Result<bool, ()>`.
|
||||
*/
|
||||
typedef enum TCResult {
|
||||
TC_RESULT_TRUE,
|
||||
TC_RESULT_FALSE,
|
||||
TC_RESULT_ERROR,
|
||||
TC_RESULT_ERROR = -1,
|
||||
TC_RESULT_FALSE = 0,
|
||||
TC_RESULT_TRUE = 1,
|
||||
} TCResult;
|
||||
|
||||
/**
|
||||
|
@ -258,30 +258,30 @@ bool tc_task_is_active(const struct TCTask *task);
|
|||
/**
|
||||
* Set a mutable task's status.
|
||||
*
|
||||
* Returns false on error.
|
||||
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
*/
|
||||
bool tc_task_set_status(struct TCTask *task, enum TCStatus status);
|
||||
enum TCResult tc_task_set_status(struct TCTask *task, enum TCStatus status);
|
||||
|
||||
/**
|
||||
* Set a mutable task's description.
|
||||
*
|
||||
* Returns false on error.
|
||||
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
*/
|
||||
bool tc_task_set_description(struct TCTask *task, struct TCString *description);
|
||||
enum TCResult tc_task_set_description(struct TCTask *task, struct TCString *description);
|
||||
|
||||
/**
|
||||
* Start a task.
|
||||
*
|
||||
* TODO: error
|
||||
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
*/
|
||||
void tc_task_start(struct TCTask *task);
|
||||
enum TCResult tc_task_start(struct TCTask *task);
|
||||
|
||||
/**
|
||||
* Stop a task.
|
||||
*
|
||||
* TODO: error
|
||||
* Returns TC_RESULT_TRUE on success and TC_RESULT_ERROR on failure.
|
||||
*/
|
||||
void tc_task_stop(struct TCTask *task);
|
||||
enum TCResult tc_task_stop(struct TCTask *task);
|
||||
|
||||
/**
|
||||
* Free a task. The given task must not be NULL. The task must not be used after this function
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue