mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
treat libc::time_t as a PassByValue
This commit is contained in:
parent
af51e0382a
commit
7ebdaa761c
4 changed files with 44 additions and 35 deletions
|
@ -1,14 +1,13 @@
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use chrono::prelude::*;
|
|
||||||
use taskchampion::Annotation;
|
use taskchampion::Annotation;
|
||||||
|
|
||||||
/// TCAnnotation contains the details of an annotation.
|
/// TCAnnotation contains the details of an annotation.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TCAnnotation {
|
pub struct TCAnnotation {
|
||||||
/// Time the annotation was made, as a UNIX epoch timestamp
|
/// Time the annotation was made. Must be nonzero.
|
||||||
pub entry: i64,
|
pub entry: libc::time_t,
|
||||||
/// Content of the annotation
|
/// Content of the annotation. Must not be NULL.
|
||||||
pub description: *mut TCString<'static>,
|
pub description: *mut TCString<'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,13 +15,16 @@ impl PassByValue for TCAnnotation {
|
||||||
type RustType = Annotation;
|
type RustType = Annotation;
|
||||||
|
|
||||||
unsafe fn from_ctype(self) -> Annotation {
|
unsafe fn from_ctype(self) -> Annotation {
|
||||||
let entry = Utc.timestamp(self.entry, 0);
|
// SAFETY:
|
||||||
|
// - any time_t value is valid
|
||||||
|
// - time_t is not zero, so unwrap is safe (see type docstring)
|
||||||
|
let entry = unsafe { self.entry.from_ctype() }.unwrap();
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// - self is owned, so we can take ownership of this TCString
|
// - self is owned, so we can take ownership of this TCString
|
||||||
// - self.description was created from a String so has valid UTF-8
|
// - self.description is a valid, non-null TCString (see type docstring)
|
||||||
// - caller did not change it (promised by caller)
|
|
||||||
let description = unsafe { TCString::take_from_arg(self.description) }
|
let description = unsafe { TCString::take_from_arg(self.description) }
|
||||||
.into_string()
|
.into_string()
|
||||||
|
// TODO: might not be valid utf-8
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Annotation { entry, description }
|
Annotation { entry, description }
|
||||||
}
|
}
|
||||||
|
@ -30,7 +32,7 @@ impl PassByValue for TCAnnotation {
|
||||||
fn as_ctype(arg: Annotation) -> Self {
|
fn as_ctype(arg: Annotation) -> Self {
|
||||||
let description: TCString = arg.description.into();
|
let description: TCString = arg.description.into();
|
||||||
TCAnnotation {
|
TCAnnotation {
|
||||||
entry: arg.entry.timestamp(),
|
entry: libc::time_t::as_ctype(Some(arg.entry)),
|
||||||
// SAFETY: caller will later free this value via tc_annotation_free
|
// SAFETY: caller will later free this value via tc_annotation_free
|
||||||
description: unsafe { description.return_val() },
|
description: unsafe { description.return_val() },
|
||||||
}
|
}
|
||||||
|
@ -40,7 +42,7 @@ impl PassByValue for TCAnnotation {
|
||||||
impl Default for TCAnnotation {
|
impl Default for TCAnnotation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
TCAnnotation {
|
TCAnnotation {
|
||||||
entry: 0,
|
entry: 0 as libc::time_t,
|
||||||
description: std::ptr::null_mut(),
|
description: std::ptr::null_mut(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
//! Trait implementations for a few atomic types
|
//! Trait implementations for a few atomic types
|
||||||
|
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
|
use chrono::prelude::*;
|
||||||
|
|
||||||
impl PassByValue for usize {
|
impl PassByValue for usize {
|
||||||
type RustType = usize;
|
type RustType = usize;
|
||||||
|
@ -13,3 +14,21 @@ impl PassByValue for usize {
|
||||||
arg
|
arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert an Option<DateTime<Utc>> to a libc::time_t, or zero if not set.
|
||||||
|
impl PassByValue for libc::time_t {
|
||||||
|
type RustType = Option<DateTime<Utc>>;
|
||||||
|
|
||||||
|
unsafe fn from_ctype(self) -> Option<DateTime<Utc>> {
|
||||||
|
if self == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Utc.timestamp(self as i64, 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ctype(arg: Option<DateTime<Utc>>) -> libc::time_t {
|
||||||
|
arg.map(|ts| ts.timestamp() as libc::time_t)
|
||||||
|
.unwrap_or(0 as libc::time_t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::util::err_to_tcstring;
|
use crate::util::err_to_tcstring;
|
||||||
use chrono::{DateTime, TimeZone, Utc};
|
use chrono::{TimeZone, Utc};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
@ -155,22 +155,6 @@ impl TryFrom<TCString<'_>> for Tag {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a DateTime<Utc> to a libc::time_t, or zero if not set.
|
|
||||||
fn to_time_t(timestamp: Option<DateTime<Utc>>) -> libc::time_t {
|
|
||||||
timestamp
|
|
||||||
.map(|ts| ts.timestamp() as libc::time_t)
|
|
||||||
.unwrap_or(0 as libc::time_t)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a libc::time_t to Option<DateTime<Utc>>, treating time zero as None
|
|
||||||
fn to_datetime(time: libc::time_t) -> Option<DateTime<Utc>> {
|
|
||||||
if time == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Utc.timestamp(time as i64, 0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TCTaskList represents a list of tasks.
|
/// TCTaskList represents a list of tasks.
|
||||||
///
|
///
|
||||||
/// The content of this struct must be treated as read-only.
|
/// The content of this struct must be treated as read-only.
|
||||||
|
@ -275,19 +259,19 @@ pub unsafe extern "C" fn tc_task_get_description<'a>(task: *mut TCTask) -> *mut
|
||||||
/// Get the entry timestamp for a task (when it was created), or 0 if not set.
|
/// Get the entry timestamp for a task (when it was created), or 0 if not set.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn tc_task_get_entry<'a>(task: *mut TCTask) -> libc::time_t {
|
pub unsafe extern "C" fn tc_task_get_entry<'a>(task: *mut TCTask) -> libc::time_t {
|
||||||
wrap(task, |task| to_time_t(task.get_entry()))
|
wrap(task, |task| libc::time_t::as_ctype(task.get_entry()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the wait timestamp for a task, or 0 if not set.
|
/// Get the wait timestamp for a task, or 0 if not set.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn tc_task_get_wait<'a>(task: *mut TCTask) -> libc::time_t {
|
pub unsafe extern "C" fn tc_task_get_wait<'a>(task: *mut TCTask) -> libc::time_t {
|
||||||
wrap(task, |task| to_time_t(task.get_wait()))
|
wrap(task, |task| libc::time_t::as_ctype(task.get_wait()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the modified timestamp for a task, or 0 if not set.
|
/// Get the modified timestamp for a task, or 0 if not set.
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn tc_task_get_modified<'a>(task: *mut TCTask) -> libc::time_t {
|
pub unsafe extern "C" fn tc_task_get_modified<'a>(task: *mut TCTask) -> libc::time_t {
|
||||||
wrap(task, |task| to_time_t(task.get_modified()))
|
wrap(task, |task| libc::time_t::as_ctype(task.get_modified()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if a task is waiting.
|
/// Check if a task is waiting.
|
||||||
|
@ -396,7 +380,8 @@ pub unsafe extern "C" fn tc_task_set_entry(task: *mut TCTask, entry: libc::time_
|
||||||
wrap_mut(
|
wrap_mut(
|
||||||
task,
|
task,
|
||||||
|task| {
|
|task| {
|
||||||
task.set_entry(to_datetime(entry))?;
|
// SAFETY: any time_t value is a valid timestamp
|
||||||
|
task.set_entry(unsafe { entry.from_ctype() })?;
|
||||||
Ok(TCResult::Ok)
|
Ok(TCResult::Ok)
|
||||||
},
|
},
|
||||||
TCResult::Error,
|
TCResult::Error,
|
||||||
|
@ -409,7 +394,8 @@ pub unsafe extern "C" fn tc_task_set_wait(task: *mut TCTask, wait: libc::time_t)
|
||||||
wrap_mut(
|
wrap_mut(
|
||||||
task,
|
task,
|
||||||
|task| {
|
|task| {
|
||||||
task.set_wait(to_datetime(wait))?;
|
// SAFETY: any time_t value is a valid timestamp
|
||||||
|
task.set_wait(unsafe { wait.from_ctype() })?;
|
||||||
Ok(TCResult::Ok)
|
Ok(TCResult::Ok)
|
||||||
},
|
},
|
||||||
TCResult::Error,
|
TCResult::Error,
|
||||||
|
@ -426,7 +412,9 @@ pub unsafe extern "C" fn tc_task_set_modified(
|
||||||
task,
|
task,
|
||||||
|task| {
|
|task| {
|
||||||
task.set_modified(
|
task.set_modified(
|
||||||
to_datetime(modified).ok_or_else(|| anyhow::anyhow!("modified cannot be zero"))?,
|
// SAFETY: any time_t value is a valid timestamp
|
||||||
|
unsafe { modified.from_ctype() }
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("modified cannot be zero"))?,
|
||||||
)?;
|
)?;
|
||||||
Ok(TCResult::Ok)
|
Ok(TCResult::Ok)
|
||||||
},
|
},
|
||||||
|
|
|
@ -122,11 +122,11 @@ typedef struct TCTask TCTask;
|
||||||
*/
|
*/
|
||||||
typedef struct TCAnnotation {
|
typedef struct TCAnnotation {
|
||||||
/**
|
/**
|
||||||
* Time the annotation was made, as a UNIX epoch timestamp
|
* Time the annotation was made. Must be nonzero.
|
||||||
*/
|
*/
|
||||||
int64_t entry;
|
time_t entry;
|
||||||
/**
|
/**
|
||||||
* Content of the annotation
|
* Content of the annotation. Must not be NULL.
|
||||||
*/
|
*/
|
||||||
struct TCString *description;
|
struct TCString *description;
|
||||||
} TCAnnotation;
|
} TCAnnotation;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue