From 8f703fd63aa562ee96794e71352c515552183416 Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Wed, 26 Jan 2022 01:29:16 +0000 Subject: [PATCH] use TCString in UUIDs --- integration-tests/src/bindings_tests/uuid.c | 37 ++++++++++++++++----- lib/src/replica.rs | 16 ++++----- lib/src/uuid.rs | 29 +++++++++++----- lib/taskchampion.h | 10 ++++-- 4 files changed, 63 insertions(+), 29 deletions(-) diff --git a/integration-tests/src/bindings_tests/uuid.c b/integration-tests/src/bindings_tests/uuid.c index 869d0cc17..2e8d0c806 100644 --- a/integration-tests/src/bindings_tests/uuid.c +++ b/integration-tests/src/bindings_tests/uuid.c @@ -8,36 +8,57 @@ static void test_uuid_creation(void) { tc_uuid_nil(); } -// converting UUIDs from string works -static void test_uuid_conversion_to_string(void) { +// converting UUIDs to a buf works +static void test_uuid_to_buf(void) { TEST_ASSERT_EQUAL(TC_UUID_STRING_BYTES, 36); TCUuid u2 = tc_uuid_nil(); char u2str[TC_UUID_STRING_BYTES]; - tc_uuid_to_str(u2, u2str); + tc_uuid_to_buf(u2, u2str); TEST_ASSERT_EQUAL_MEMORY("00000000-0000-0000-0000-000000000000", u2str, TC_UUID_STRING_BYTES); } +// converting UUIDs to a buf works +static void test_uuid_to_str(void) { + TCUuid u = tc_uuid_nil(); + TCString *s = tc_uuid_to_str(u); + TEST_ASSERT_EQUAL_STRING( + "00000000-0000-0000-0000-000000000000", + tc_string_content(s)); + tc_string_free(s); +} + +// converting valid UUIDs from string works +static void test_uuid_valid_from_str(void) { + TCUuid u; + char *ustr = "23cb25e0-5d1a-4932-8131-594ac6d3a843"; + TEST_ASSERT_TRUE(tc_uuid_from_str(tc_string_borrow(ustr), &u)); + TEST_ASSERT_EQUAL(0x23, u.bytes[0]); + TEST_ASSERT_EQUAL(0x43, u.bytes[15]); +} + // converting invalid UUIDs from string fails as expected static void test_uuid_invalid_string_fails(void) { TCUuid u; - char ustr[36] = "not-a-valid-uuid"; - TEST_ASSERT_FALSE(tc_uuid_from_str(ustr, &u)); + char *ustr = "not-a-valid-uuid"; + TEST_ASSERT_FALSE(tc_uuid_from_str(tc_string_borrow(ustr), &u)); } // converting invalid UTF-8 UUIDs from string fails as expected static void test_uuid_bad_utf8(void) { TCUuid u; - char ustr[36] = "\xf0\x28\x8c\xbc"; - TEST_ASSERT_FALSE(tc_uuid_from_str(ustr, &u)); + char *ustr = "\xf0\x28\x8c\xbc"; + TEST_ASSERT_FALSE(tc_uuid_from_str(tc_string_borrow(ustr), &u)); } int uuid_tests(void) { UNITY_BEGIN(); // each test case above should be named here, in order. RUN_TEST(test_uuid_creation); - RUN_TEST(test_uuid_conversion_to_string); + RUN_TEST(test_uuid_valid_from_str); + RUN_TEST(test_uuid_to_buf); + RUN_TEST(test_uuid_to_str); RUN_TEST(test_uuid_invalid_string_fails); RUN_TEST(test_uuid_bad_utf8); return UNITY_END(); diff --git a/lib/src/replica.rs b/lib/src/replica.rs index 7ae4cc286..3d2eafd2f 100644 --- a/lib/src/replica.rs +++ b/lib/src/replica.rs @@ -80,13 +80,10 @@ pub extern "C" fn tc_replica_new_on_disk<'a>( })) } -/* - * TODO: - * - tc_replica_all_tasks - * - tc_replica_all_task_uuids - * - tc_replica_working_set - * - tc_replica_get_task - */ +// TODO: tc_replica_all_tasks +// TODO: tc_replica_all_task_uuids +// TODO: tc_replica_working_set +// TODO: tc_replica_get_task /// Create a new task. The task must not already exist. /// @@ -108,9 +105,8 @@ pub extern "C" fn tc_replica_new_task<'a>( ) } -/* - tc_replica_import_task_with_uuid - * - tc_replica_sync - */ +// TODO: tc_replica_import_task_with_uuid +// TODO: tc_replica_sync /// Undo local operations until the most recent UndoPoint. /// diff --git a/lib/src/uuid.rs b/lib/src/uuid.rs index 5e3492bea..f25399909 100644 --- a/lib/src/uuid.rs +++ b/lib/src/uuid.rs @@ -1,3 +1,4 @@ +use crate::string::TCString; use libc; use taskchampion::Uuid; @@ -33,31 +34,41 @@ pub extern "C" fn tc_uuid_nil() -> TCUuid { } /// Length, in bytes, of a C string containing a TCUuid. +// TODO: why not a const? #[no_mangle] pub static TC_UUID_STRING_BYTES: usize = ::uuid::adapter::Hyphenated::LENGTH; /// Write the string representation of a TCUuid into the given buffer, which must be /// at least TC_UUID_STRING_BYTES long. No NUL terminator is added. #[no_mangle] -pub extern "C" fn tc_uuid_to_str<'a>(uuid: TCUuid, out: *mut libc::c_char) { - debug_assert!(!out.is_null()); +pub extern "C" fn tc_uuid_to_buf<'a>(uuid: TCUuid, buf: *mut libc::c_char) { + debug_assert!(!buf.is_null()); let buf: &'a mut [u8] = unsafe { - std::slice::from_raw_parts_mut(out as *mut u8, ::uuid::adapter::Hyphenated::LENGTH) + std::slice::from_raw_parts_mut(buf as *mut u8, ::uuid::adapter::Hyphenated::LENGTH) }; let uuid: Uuid = uuid.into(); uuid.to_hyphenated().encode_lower(buf); } +/// Write the string representation of a TCUuid into the given buffer, which must be +/// at least TC_UUID_STRING_BYTES long. No NUL terminator is added. +#[no_mangle] +pub extern "C" fn tc_uuid_to_str(uuid: TCUuid) -> *mut TCString<'static> { + let uuid: Uuid = uuid.into(); + let s = uuid.to_string(); + TCString::from(s).return_val() +} + /// Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns /// false on failure. #[no_mangle] -pub extern "C" fn tc_uuid_from_str<'a>(val: *const libc::c_char, out: *mut TCUuid) -> bool { - debug_assert!(!val.is_null()); - debug_assert!(!out.is_null()); - let slice = unsafe { std::slice::from_raw_parts(val as *const u8, TC_UUID_STRING_BYTES) }; - if let Ok(s) = std::str::from_utf8(slice) { +pub extern "C" fn tc_uuid_from_str<'a>(s: *mut TCString, uuid_out: *mut TCUuid) -> bool { + debug_assert!(!s.is_null()); + debug_assert!(!uuid_out.is_null()); + let s = TCString::from_arg(s); + if let Ok(s) = s.as_str() { if let Ok(u) = Uuid::parse_str(s) { - unsafe { *out = u.into() }; + unsafe { *uuid_out = u.into() }; return true; } } diff --git a/lib/taskchampion.h b/lib/taskchampion.h index 786ead2c0..b09a8f4d5 100644 --- a/lib/taskchampion.h +++ b/lib/taskchampion.h @@ -202,13 +202,19 @@ struct TCUuid tc_uuid_nil(void); * Write the string representation of a TCUuid into the given buffer, which must be * at least TC_UUID_STRING_BYTES long. No NUL terminator is added. */ -void tc_uuid_to_str(struct TCUuid uuid, char *out); +void tc_uuid_to_buf(struct TCUuid uuid, char *buf); + +/** + * Write the string representation of a TCUuid into the given buffer, which must be + * at least TC_UUID_STRING_BYTES long. No NUL terminator is added. + */ +struct TCString *tc_uuid_to_str(struct TCUuid uuid); /** * Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns * false on failure. */ -bool tc_uuid_from_str(const char *val, struct TCUuid *out); +bool tc_uuid_from_str(struct TCString *s, struct TCUuid *uuid_out); #ifdef __cplusplus } // extern "C"