add TC prefix to types, too

This commit is contained in:
Dustin J. Mitchell
2022-01-23 19:57:42 +00:00
parent 46e08bc040
commit 821118106a
6 changed files with 69 additions and 77 deletions

View File

@@ -2,14 +2,14 @@
#include "doctest.h" #include "doctest.h"
#include "taskchampion.h" #include "taskchampion.h"
TEST_CASE("creating an in-memory Replica does not crash") { TEST_CASE("creating an in-memory TCReplica does not crash") {
Replica *rep = tc_replica_new(NULL); TCReplica *rep = tc_replica_new(NULL);
CHECK(tc_replica_error(rep) == NULL); CHECK(tc_replica_error(rep) == NULL);
tc_replica_free(rep); tc_replica_free(rep);
} }
TEST_CASE("undo on an empty in-memory Replica does nothing") { TEST_CASE("undo on an empty in-memory TCReplica does nothing") {
Replica *rep = tc_replica_new(NULL); TCReplica *rep = tc_replica_new(NULL);
CHECK(tc_replica_error(rep) == NULL); CHECK(tc_replica_error(rep) == NULL);
int rv = tc_replica_undo(rep); int rv = tc_replica_undo(rep);
CHECK(rv == 0); CHECK(rv == 0);

View File

@@ -3,12 +3,12 @@
#include "taskchampion.h" #include "taskchampion.h"
TEST_CASE("creating UUIDs does not crash") { TEST_CASE("creating UUIDs does not crash") {
Uuid u1 = tc_uuid_new_v4(); TCUuid u1 = tc_uuid_new_v4();
Uuid u2 = tc_uuid_nil(); TCUuid u2 = tc_uuid_nil();
} }
TEST_CASE("converting UUIDs to string works") { TEST_CASE("converting UUIDs to string works") {
Uuid u2 = tc_uuid_nil(); TCUuid u2 = tc_uuid_nil();
REQUIRE(TC_UUID_STRING_BYTES == 36); REQUIRE(TC_UUID_STRING_BYTES == 36);
char u2str[TC_UUID_STRING_BYTES]; char u2str[TC_UUID_STRING_BYTES];
@@ -17,22 +17,22 @@ TEST_CASE("converting UUIDs to string works") {
} }
TEST_CASE("converting UUIDs from string works") { TEST_CASE("converting UUIDs from string works") {
Uuid u; TCUuid u;
char ustr[TC_UUID_STRING_BYTES] = "fdc314b7-f938-4845-b8d1-95716e4eb762"; char ustr[TC_UUID_STRING_BYTES] = "fdc314b7-f938-4845-b8d1-95716e4eb762";
CHECK(tc_uuid_from_str(ustr, &u)); CHECK(tc_uuid_from_str(ustr, &u));
CHECK(u._0[0] == 0xfd); CHECK(u.bytes[0] == 0xfd);
// .. if these two are correct, probably it worked :) // .. if these two bytes are correct, then it probably worked :)
CHECK(u._0[15] == 0x62); CHECK(u.bytes[15] == 0x62);
} }
TEST_CASE("converting invalid UUIDs from string fails as expected") { TEST_CASE("converting invalid UUIDs from string fails as expected") {
Uuid u; TCUuid u;
char ustr[TC_UUID_STRING_BYTES] = "not-a-valid-uuid"; char ustr[TC_UUID_STRING_BYTES] = "not-a-valid-uuid";
CHECK(!tc_uuid_from_str(ustr, &u)); CHECK(!tc_uuid_from_str(ustr, &u));
} }
TEST_CASE("converting invalid UTF-8 UUIDs from string fails as expected") { TEST_CASE("converting invalid UTF-8 UUIDs from string fails as expected") {
Uuid u; TCUuid u;
char ustr[TC_UUID_STRING_BYTES] = "\xf0\x28\x8c\xbc"; char ustr[TC_UUID_STRING_BYTES] = "\xf0\x28\x8c\xbc";
CHECK(!tc_uuid_from_str(ustr, &u)); CHECK(!tc_uuid_from_str(ustr, &u));
} }

View File

@@ -10,16 +10,6 @@ fn main() {
.with_language(Language::C) .with_language(Language::C)
.with_config(Config { .with_config(Config {
cpp_compat: true, cpp_compat: true,
export: ExportConfig {
item_types: vec![
ItemType::Structs,
ItemType::Globals,
ItemType::Functions,
ItemType::Constants,
ItemType::OpaqueItems,
],
..Default::default()
},
..Default::default() ..Default::default()
}) })
.generate() .generate()

View File

@@ -1,30 +1,29 @@
use libc::c_char; use libc::c_char;
use std::ffi::{CStr, CString, OsStr}; use std::ffi::{CStr, CString, OsStr};
use std::path::PathBuf; use std::path::PathBuf;
use taskchampion::Replica as TCReplica; use taskchampion::{Replica, StorageConfig};
use taskchampion::StorageConfig;
// TODO: unix-only // TODO: unix-only
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
/// A replica represents an instance of a user's task data, providing an easy interface /// A replica represents an instance of a user's task data, providing an easy interface
/// for querying and modifying that data. /// for querying and modifying that data.
pub struct Replica { pub struct TCReplica {
// TODO: make this an option so that it can be take()n when holding a mut ref // TODO: make this an option so that it can be take()n when holding a mut ref
inner: TCReplica, inner: Replica,
error: Option<CString>, error: Option<CString>,
} }
/// Create a new Replica. /// Create a new TCReplica.
/// ///
/// If path is NULL, then an in-memory replica is created. Otherwise, path is the path to the /// If path is NULL, then an in-memory replica is created. Otherwise, path is the path to the
/// on-disk storage for this replica. The path argument is no longer referenced after return. /// on-disk storage for this replica. The path argument is no longer referenced after return.
/// ///
/// Returns NULL on error; see tc_replica_error. /// Returns NULL on error; see tc_replica_error.
/// ///
/// Replicas are not threadsafe. /// TCReplicas are not threadsafe.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_replica_new<'a>(path: *const c_char) -> *mut Replica { pub extern "C" fn tc_replica_new<'a>(path: *const c_char) -> *mut TCReplica {
let storage_res = if path.is_null() { let storage_res = if path.is_null() {
StorageConfig::InMemory.into_storage() StorageConfig::InMemory.into_storage()
} else { } else {
@@ -40,23 +39,23 @@ pub extern "C" fn tc_replica_new<'a>(path: *const c_char) -> *mut Replica {
Err(_) => return std::ptr::null_mut(), Err(_) => return std::ptr::null_mut(),
}; };
Box::into_raw(Box::new(Replica { Box::into_raw(Box::new(TCReplica {
inner: TCReplica::new(storage), inner: Replica::new(storage),
error: None, error: None,
})) }))
} }
/// Utility function to safely convert *mut Replica into &mut Replica /// Utility function to safely convert *mut TCReplica into &mut TCReplica
fn rep_ref(rep: *mut Replica) -> &'static mut Replica { fn rep_ref(rep: *mut TCReplica) -> &'static mut TCReplica {
debug_assert!(!rep.is_null()); debug_assert!(!rep.is_null());
unsafe { &mut *rep } unsafe { &mut *rep }
} }
fn wrap<'a, T, F>(rep: *mut Replica, f: F, err_value: T) -> T fn wrap<'a, T, F>(rep: *mut TCReplica, f: F, err_value: T) -> T
where where
F: FnOnce(&mut TCReplica) -> anyhow::Result<T>, F: FnOnce(&mut Replica) -> anyhow::Result<T>,
{ {
let rep: &'a mut Replica = rep_ref(rep); let rep: &'a mut TCReplica = rep_ref(rep);
match f(&mut rep.inner) { match f(&mut rep.inner) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
@@ -76,7 +75,7 @@ where
/// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were /// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were
/// undone. /// undone.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_replica_undo<'a>(rep: *mut Replica) -> i32 { pub extern "C" fn tc_replica_undo<'a>(rep: *mut TCReplica) -> i32 {
wrap(rep, |rep| Ok(if rep.undo()? { 1 } else { 0 }), -1) wrap(rep, |rep| Ok(if rep.undo()? { 1 } else { 0 }), -1)
} }
@@ -84,8 +83,8 @@ pub extern "C" fn tc_replica_undo<'a>(rep: *mut Replica) -> i32 {
/// ///
/// The returned string is valid until the next replica operation. /// The returned string is valid until the next replica operation.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_replica_error<'a>(rep: *mut Replica) -> *const c_char { pub extern "C" fn tc_replica_error<'a>(rep: *mut TCReplica) -> *const c_char {
let rep: &'a Replica = rep_ref(rep); let rep: &'a TCReplica = rep_ref(rep);
if let Some(ref e) = rep.error { if let Some(ref e) = rep.error {
e.as_ptr() e.as_ptr()
} else { } else {
@@ -93,8 +92,8 @@ pub extern "C" fn tc_replica_error<'a>(rep: *mut Replica) -> *const c_char {
} }
} }
/// Free a Replica. /// Free a TCReplica.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_replica_free(rep: *mut Replica) { pub extern "C" fn tc_replica_free(rep: *mut TCReplica) {
drop(unsafe { Box::from_raw(rep) }); drop(unsafe { Box::from_raw(rep) });
} }

View File

@@ -1,60 +1,63 @@
use libc; use libc;
use taskchampion::Uuid as TcUuid; use taskchampion::Uuid;
/// Uuid is used as a task identifier. Uuids do not contain any pointers and need not be freed. /// TCUuid is used as a task identifier. Uuids do not contain any pointers and need not be freed.
/// Uuids are typically treated as opaque, but the bytes are available in big-endian format.
///
/// cbindgen:field-names=[bytes]
#[repr(C)] #[repr(C)]
pub struct Uuid([u8; 16]); pub struct TCUuid([u8; 16]);
impl From<TcUuid> for Uuid { impl From<Uuid> for TCUuid {
fn from(uuid: TcUuid) -> Uuid { fn from(uuid: Uuid) -> TCUuid {
// TODO: can we avoid clone here? // TODO: can we avoid clone here?
Uuid(uuid.as_bytes().clone()) TCUuid(uuid.as_bytes().clone())
} }
} }
impl From<Uuid> for TcUuid { impl From<TCUuid> for Uuid {
fn from(uuid: Uuid) -> TcUuid { fn from(uuid: TCUuid) -> Uuid {
TcUuid::from_bytes(uuid.0) Uuid::from_bytes(uuid.0)
} }
} }
/// Create a new, randomly-generated UUID. /// Create a new, randomly-generated UUID.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_uuid_new_v4() -> Uuid { pub extern "C" fn tc_uuid_new_v4() -> TCUuid {
TcUuid::new_v4().into() Uuid::new_v4().into()
} }
/// Create a new UUID with the nil value. /// Create a new UUID with the nil value.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_uuid_nil() -> Uuid { pub extern "C" fn tc_uuid_nil() -> TCUuid {
TcUuid::nil().into() Uuid::nil().into()
} }
/// Length, in bytes, of a C string containing a Uuid. /// Length, in bytes, of a C string containing a TCUuid.
#[no_mangle] #[no_mangle]
pub static TC_UUID_STRING_BYTES: usize = ::uuid::adapter::Hyphenated::LENGTH; pub static TC_UUID_STRING_BYTES: usize = ::uuid::adapter::Hyphenated::LENGTH;
/// Write the string representation of a Uuid into the given buffer, which must be /// 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. /// at least TC_UUID_STRING_BYTES long. No NUL terminator is added.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_uuid_to_str<'a>(uuid: Uuid, out: *mut libc::c_char) { pub extern "C" fn tc_uuid_to_str<'a>(uuid: TCUuid, out: *mut libc::c_char) {
debug_assert!(!out.is_null()); debug_assert!(!out.is_null());
let buf: &'a mut [u8] = unsafe { 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(out as *mut u8, ::uuid::adapter::Hyphenated::LENGTH)
}; };
let uuid: TcUuid = uuid.into(); let uuid: Uuid = uuid.into();
uuid.to_hyphenated().encode_lower(buf); uuid.to_hyphenated().encode_lower(buf);
} }
/// Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns /// Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns
/// false on failure. /// false on failure.
#[no_mangle] #[no_mangle]
pub extern "C" fn tc_uuid_from_str<'a>(val: *const libc::c_char, out: *mut Uuid) -> bool { 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!(!val.is_null());
debug_assert!(!out.is_null()); debug_assert!(!out.is_null());
let slice = unsafe { std::slice::from_raw_parts(val as *const u8, TC_UUID_STRING_BYTES) }; 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) { if let Ok(s) = std::str::from_utf8(slice) {
if let Ok(u) = TcUuid::parse_str(s) { if let Ok(u) = Uuid::parse_str(s) {
unsafe { *out = u.into() }; unsafe { *out = u.into() };
return true; return true;
} }

View File

@@ -6,53 +6,53 @@
/// A replica represents an instance of a user's task data, providing an easy interface /// A replica represents an instance of a user's task data, providing an easy interface
/// for querying and modifying that data. /// for querying and modifying that data.
struct Replica; struct TCReplica;
/// Uuid is used as a task identifier. Uuids do not contain any pointers and need not be freed. /// TCUuid is used as a task identifier. Uuids do not contain any pointers and need not be freed.
struct Uuid { struct TCUuid {
uint8_t _0[16]; uint8_t bytes[16];
}; };
extern "C" { extern "C" {
extern const uintptr_t TC_UUID_STRING_BYTES; extern const uintptr_t TC_UUID_STRING_BYTES;
/// Create a new Replica. /// Create a new TCReplica.
/// ///
/// If path is NULL, then an in-memory replica is created. Otherwise, path is the path to the /// If path is NULL, then an in-memory replica is created. Otherwise, path is the path to the
/// on-disk storage for this replica. The path argument is no longer referenced after return. /// on-disk storage for this replica. The path argument is no longer referenced after return.
/// ///
/// Returns NULL on error; see tc_replica_error. /// Returns NULL on error; see tc_replica_error.
/// ///
/// Replicas are not threadsafe. /// TCReplicas are not threadsafe.
Replica *tc_replica_new(const char *path); TCReplica *tc_replica_new(const char *path);
/// Undo local operations until the most recent UndoPoint. /// Undo local operations until the most recent UndoPoint.
/// ///
/// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were /// Returns -1 on error, 0 if there are no local operations to undo, and 1 if operations were
/// undone. /// undone.
int32_t tc_replica_undo(Replica *rep); int32_t tc_replica_undo(TCReplica *rep);
/// Get the latest error for a replica, or NULL if the last operation succeeded. /// Get the latest error for a replica, or NULL if the last operation succeeded.
/// ///
/// The returned string is valid until the next replica operation. /// The returned string is valid until the next replica operation.
const char *tc_replica_error(Replica *rep); const char *tc_replica_error(TCReplica *rep);
/// Free a Replica. /// Free a TCReplica.
void tc_replica_free(Replica *rep); void tc_replica_free(TCReplica *rep);
/// Create a new, randomly-generated UUID. /// Create a new, randomly-generated UUID.
Uuid tc_uuid_new_v4(); TCUuid tc_uuid_new_v4();
/// Create a new UUID with the nil value. /// Create a new UUID with the nil value.
Uuid tc_uuid_nil(); TCUuid tc_uuid_nil();
/// Write the string representation of a Uuid into the given buffer, which must be /// 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. /// at least TC_UUID_STRING_BYTES long. No NUL terminator is added.
void tc_uuid_to_str(Uuid uuid, char *out); void tc_uuid_to_str(TCUuid uuid, char *out);
/// Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns /// Parse the given value as a UUID. The value must be exactly TC_UUID_STRING_BYTES long. Returns
/// false on failure. /// false on failure.
bool tc_uuid_from_str(const char *val, Uuid *out); bool tc_uuid_from_str(const char *val, TCUuid *out);
} // extern "C" } // extern "C"