mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +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);
|
TCUuid uuid = tc_task_get_uuid(task);
|
||||||
|
|
||||||
tc_task_to_mut(task, rep);
|
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));
|
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_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
|
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);
|
||||||
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_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));
|
||||||
tc_task_start(task);
|
TEST_ASSERT_EQUAL(TC_RESULT_TRUE, tc_task_start(task));
|
||||||
TEST_ASSERT_TRUE(tc_task_is_active(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));
|
TEST_ASSERT_FALSE(tc_task_is_active(task));
|
||||||
|
|
||||||
tc_task_free(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
|
/// A result combines a boolean success value with
|
||||||
/// an error response. It is equivalent to `Result<bool, ()>`.
|
/// 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(C)]
|
||||||
pub enum TCResult {
|
pub enum TCResult {
|
||||||
True,
|
Error = -1,
|
||||||
False,
|
False = 0,
|
||||||
Error,
|
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 std::ops::Deref;
|
||||||
use taskchampion::{Task, TaskMut};
|
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
|
fn wrap<'a, T, F>(task: *const TCTask, f: F) -> T
|
||||||
where
|
where
|
||||||
F: FnOnce(&Task) -> T,
|
F: FnOnce(&Task) -> T,
|
||||||
|
@ -131,8 +134,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Utility function to get a mutable reference to the underlying Task. The
|
/// Utility function to get a mutable reference to the underlying Task. The
|
||||||
/// TCTask must be mutable.
|
/// TCTask must be mutable. The inner function may use `?` syntax to return an
|
||||||
fn wrap_mut<'a, T, F>(task: *mut TCTask, f: F) -> T
|
/// 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
|
where
|
||||||
F: FnOnce(&mut TaskMut) -> anyhow::Result<T>,
|
F: FnOnce(&mut TaskMut) -> anyhow::Result<T>,
|
||||||
{
|
{
|
||||||
|
@ -145,8 +149,13 @@ where
|
||||||
TCTask::Mutable(ref mut t, _) => t,
|
TCTask::Mutable(ref mut t, _) => t,
|
||||||
TCTask::Invalid => unreachable!(),
|
TCTask::Invalid => unreachable!(),
|
||||||
};
|
};
|
||||||
|
match f(task) {
|
||||||
|
Ok(rv) => rv,
|
||||||
|
Err(e) => {
|
||||||
// TODO: add TCTask error handling, like replica
|
// TODO: add TCTask error handling, like replica
|
||||||
f(task).unwrap()
|
err_value
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an immutable task into a mutable task.
|
/// 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.
|
/// Set a mutable task's status.
|
||||||
///
|
///
|
||||||
/// Returns false on error.
|
/// 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) -> bool {
|
pub extern "C" fn tc_task_set_status<'a>(task: *mut TCTask, status: TCStatus) -> TCResult {
|
||||||
wrap_mut(task, |task| {
|
wrap_mut(
|
||||||
|
task,
|
||||||
|
|task| {
|
||||||
task.set_status(status.into())?;
|
task.set_status(status.into())?;
|
||||||
Ok(true)
|
Ok(TCResult::True)
|
||||||
})
|
},
|
||||||
|
TCResult::Error,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set a mutable task's description.
|
/// Set a mutable task's description.
|
||||||
///
|
///
|
||||||
/// Returns false on error.
|
/// 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,
|
||||||
description: *mut TCString,
|
description: *mut TCString,
|
||||||
) -> bool {
|
) -> TCResult {
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// - tcstring is not NULL (promised by caller)
|
// - tcstring is not NULL (promised by caller)
|
||||||
// - caller is exclusive owner of tcstring (implicitly promised by caller)
|
// - caller is exclusive owner of tcstring (implicitly promised by caller)
|
||||||
let description = unsafe { TCString::from_arg(description) };
|
let description = unsafe { TCString::from_arg(description) };
|
||||||
wrap_mut(task, |task| {
|
wrap_mut(
|
||||||
|
task,
|
||||||
|
|task| {
|
||||||
task.set_description(description.as_str()?.to_string())?;
|
task.set_description(description.as_str()?.to_string())?;
|
||||||
Ok(true)
|
Ok(TCResult::True)
|
||||||
})
|
},
|
||||||
|
TCResult::Error,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: tc_task_set_description
|
// TODO: tc_task_set_description
|
||||||
|
@ -272,24 +289,32 @@ pub extern "C" fn tc_task_set_description<'a>(
|
||||||
|
|
||||||
/// Start a task.
|
/// Start a task.
|
||||||
///
|
///
|
||||||
/// TODO: error
|
/// 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) {
|
pub extern "C" fn tc_task_start<'a>(task: *mut TCTask) -> TCResult {
|
||||||
wrap_mut(task, |task| {
|
wrap_mut(
|
||||||
|
task,
|
||||||
|
|task| {
|
||||||
task.start()?;
|
task.start()?;
|
||||||
Ok(())
|
Ok(TCResult::True)
|
||||||
})
|
},
|
||||||
|
TCResult::Error,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop a task.
|
/// Stop a task.
|
||||||
///
|
///
|
||||||
/// TODO: error
|
/// 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) {
|
pub extern "C" fn tc_task_stop<'a>(task: *mut TCTask) -> TCResult {
|
||||||
wrap_mut(task, |task| {
|
wrap_mut(
|
||||||
|
task,
|
||||||
|
|task| {
|
||||||
task.stop()?;
|
task.stop()?;
|
||||||
Ok(())
|
Ok(TCResult::True)
|
||||||
})
|
},
|
||||||
|
TCResult::Error,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: tc_task_done
|
// TODO: tc_task_done
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
* an error response. It is equivalent to `Result<bool, ()>`.
|
* an error response. It is equivalent to `Result<bool, ()>`.
|
||||||
*/
|
*/
|
||||||
typedef enum TCResult {
|
typedef enum TCResult {
|
||||||
TC_RESULT_TRUE,
|
TC_RESULT_ERROR = -1,
|
||||||
TC_RESULT_FALSE,
|
TC_RESULT_FALSE = 0,
|
||||||
TC_RESULT_ERROR,
|
TC_RESULT_TRUE = 1,
|
||||||
} TCResult;
|
} TCResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -258,30 +258,30 @@ bool tc_task_is_active(const struct TCTask *task);
|
||||||
/**
|
/**
|
||||||
* Set a mutable task's status.
|
* 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.
|
* 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.
|
* 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.
|
* 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
|
* 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