taskchampion_lib/
workingset.rs

1use crate::traits::*;
2use crate::types::*;
3use taskchampion::{Uuid, WorkingSet};
4
5#[ffizz_header::item]
6#[ffizz(order = 1100)]
7/// ***** TCWorkingSet *****
8///
9/// A TCWorkingSet represents a snapshot of the working set for a replica.  It is not automatically
10/// updated based on changes in the replica.  Its lifetime is independent of the replica and it can
11/// be freed at any time.
12///
13/// To iterate over a working set, search indexes 1 through largest_index.
14///
15/// # Safety
16///
17/// The `*TCWorkingSet` returned from `tc_replica_working_set` is owned by the caller and
18/// must later be freed to avoid a memory leak.  Its lifetime is independent of the replica
19/// from which it was generated.
20///
21/// Any function taking a `*TCWorkingSet` requires:
22///  - the pointer must not be NUL;
23///  - the pointer must be one previously returned from `tc_replica_working_set`
24///  - the memory referenced by the pointer must never be accessed by C code; and
25///  - except for `tc_replica_free`, ownership of a `*TCWorkingSet` remains with the caller.
26///
27/// Once passed to `tc_replica_free`, a `*TCWorkingSet` becomes invalid and must not be used again.
28///
29/// TCWorkingSet is not threadsafe.
30///
31/// ```c
32/// typedef struct TCWorkingSet TCWorkingSet;
33/// ```
34pub struct TCWorkingSet(WorkingSet);
35
36impl PassByPointer for TCWorkingSet {}
37
38impl From<WorkingSet> for TCWorkingSet {
39    fn from(ws: WorkingSet) -> TCWorkingSet {
40        TCWorkingSet(ws)
41    }
42}
43
44/// Utility function to get a shared reference to the underlying WorkingSet.
45fn wrap<T, F>(ws: *mut TCWorkingSet, f: F) -> T
46where
47    F: FnOnce(&WorkingSet) -> T,
48{
49    // SAFETY:
50    //  - ws is not null (promised by caller)
51    //  - ws outlives 'a (promised by caller)
52    let tcws: &TCWorkingSet = unsafe { TCWorkingSet::from_ptr_arg_ref(ws) };
53    f(&tcws.0)
54}
55
56#[ffizz_header::item]
57#[ffizz(order = 1101)]
58/// Get the working set's length, or the number of UUIDs it contains.
59///
60/// ```c
61/// EXTERN_C size_t tc_working_set_len(struct TCWorkingSet *ws);
62/// ```
63#[no_mangle]
64pub unsafe extern "C" fn tc_working_set_len(ws: *mut TCWorkingSet) -> usize {
65    wrap(ws, |ws| ws.len())
66}
67
68#[ffizz_header::item]
69#[ffizz(order = 1101)]
70/// Get the working set's largest index.
71///
72/// ```c
73/// EXTERN_C size_t tc_working_set_largest_index(struct TCWorkingSet *ws);
74/// ```
75#[no_mangle]
76pub unsafe extern "C" fn tc_working_set_largest_index(ws: *mut TCWorkingSet) -> usize {
77    wrap(ws, |ws| ws.largest_index())
78}
79
80#[ffizz_header::item]
81#[ffizz(order = 1101)]
82/// Get the UUID for the task at the given index.  Returns true if the UUID exists in the working
83/// set.  If not, returns false and does not change uuid_out.
84///
85/// ```c
86/// EXTERN_C bool tc_working_set_by_index(struct TCWorkingSet *ws, size_t index, struct TCUuid *uuid_out);
87/// ```
88#[no_mangle]
89pub unsafe extern "C" fn tc_working_set_by_index(
90    ws: *mut TCWorkingSet,
91    index: usize,
92    uuid_out: *mut TCUuid,
93) -> bool {
94    debug_assert!(!uuid_out.is_null());
95    wrap(ws, |ws| {
96        if let Some(uuid) = ws.by_index(index) {
97            // SAFETY:
98            //  - uuid_out is not NULL (promised by caller)
99            //  - alignment is not required
100            unsafe { TCUuid::val_to_arg_out(uuid, uuid_out) };
101            true
102        } else {
103            false
104        }
105    })
106}
107
108#[ffizz_header::item]
109#[ffizz(order = 1101)]
110/// Get the working set index for the task with the given UUID.  Returns 0 if the task is not in
111/// the working set.
112///
113/// ```c
114/// EXTERN_C size_t tc_working_set_by_uuid(struct TCWorkingSet *ws, struct TCUuid uuid);
115/// ```
116#[no_mangle]
117pub unsafe extern "C" fn tc_working_set_by_uuid(ws: *mut TCWorkingSet, uuid: TCUuid) -> usize {
118    wrap(ws, |ws| {
119        // SAFETY:
120        //  - tcuuid is a valid TCUuid (all byte patterns are valid)
121        let uuid: Uuid = unsafe { TCUuid::val_from_arg(uuid) };
122        ws.by_uuid(uuid).unwrap_or(0)
123    })
124}
125
126#[ffizz_header::item]
127#[ffizz(order = 1102)]
128/// Free a TCWorkingSet.  The given value must not be NULL.  The value must not be used after this
129/// function returns, and must not be freed more than once.
130///
131/// ```c
132/// EXTERN_C void tc_working_set_free(struct TCWorkingSet *ws);
133/// ```
134#[no_mangle]
135pub unsafe extern "C" fn tc_working_set_free(ws: *mut TCWorkingSet) {
136    // SAFETY:
137    //  - rep is not NULL (promised by caller)
138    //  - caller will not use the TCWorkingSet after this (promised by caller)
139    let ws = unsafe { TCWorkingSet::take_from_ptr_arg(ws) };
140    drop(ws);
141}