mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
refactor annotations to handle invalid strings
This commit is contained in:
parent
7ebdaa761c
commit
76cbc2880b
2 changed files with 19 additions and 16 deletions
|
@ -1,6 +1,6 @@
|
||||||
use crate::traits::*;
|
use crate::traits::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use taskchampion::Annotation;
|
use chrono::prelude::*;
|
||||||
|
|
||||||
/// TCAnnotation contains the details of an annotation.
|
/// TCAnnotation contains the details of an annotation.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -12,9 +12,11 @@ pub struct TCAnnotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PassByValue for TCAnnotation {
|
impl PassByValue for TCAnnotation {
|
||||||
type RustType = Annotation;
|
// NOTE: we cannot use `RustType = Annotation` here because conversion of the
|
||||||
|
// TCString to a String can fail.
|
||||||
|
type RustType = (DateTime<Utc>, TCString<'static>);
|
||||||
|
|
||||||
unsafe fn from_ctype(self) -> Annotation {
|
unsafe fn from_ctype(self) -> Self::RustType {
|
||||||
// SAFETY:
|
// SAFETY:
|
||||||
// - any time_t value is valid
|
// - any time_t value is valid
|
||||||
// - time_t is not zero, so unwrap is safe (see type docstring)
|
// - time_t is not zero, so unwrap is safe (see type docstring)
|
||||||
|
@ -22,18 +24,14 @@ impl PassByValue for TCAnnotation {
|
||||||
// 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 is a valid, non-null TCString (see type docstring)
|
// - self.description is a valid, non-null TCString (see type docstring)
|
||||||
let description = unsafe { TCString::take_from_arg(self.description) }
|
let description = unsafe { TCString::take_from_arg(self.description) };
|
||||||
.into_string()
|
(entry, description)
|
||||||
// TODO: might not be valid utf-8
|
|
||||||
.unwrap();
|
|
||||||
Annotation { entry, description }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ctype(arg: Annotation) -> Self {
|
fn as_ctype((entry, description): Self::RustType) -> Self {
|
||||||
let description: TCString = arg.description.into();
|
|
||||||
TCAnnotation {
|
TCAnnotation {
|
||||||
entry: libc::time_t::as_ctype(Some(arg.entry)),
|
entry: libc::time_t::as_ctype(Some(entry)),
|
||||||
// SAFETY: caller will later free this value via tc_annotation_free
|
// SAFETY: caller assumes ownership of this value
|
||||||
description: unsafe { description.return_val() },
|
description: unsafe { description.return_val() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::convert::TryFrom;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use taskchampion::{Tag, Task, TaskMut};
|
use taskchampion::{Annotation, Tag, Task, TaskMut};
|
||||||
|
|
||||||
/// A task, as publicly exposed by this library.
|
/// A task, as publicly exposed by this library.
|
||||||
///
|
///
|
||||||
|
@ -331,7 +331,10 @@ pub unsafe extern "C" fn tc_task_get_annotations<'a>(task: *mut TCTask) -> TCAnn
|
||||||
wrap(task, |task| {
|
wrap(task, |task| {
|
||||||
let vec: Vec<TCAnnotation> = task
|
let vec: Vec<TCAnnotation> = task
|
||||||
.get_annotations()
|
.get_annotations()
|
||||||
.map(|a| TCAnnotation::as_ctype(a))
|
.map(|a| {
|
||||||
|
let description = TCString::from(a.description);
|
||||||
|
TCAnnotation::as_ctype((a.entry, description))
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
TCAnnotationList::return_val(vec)
|
TCAnnotationList::return_val(vec)
|
||||||
})
|
})
|
||||||
|
@ -513,11 +516,13 @@ pub unsafe extern "C" fn tc_task_add_annotation(
|
||||||
annotation: *mut TCAnnotation,
|
annotation: *mut TCAnnotation,
|
||||||
) -> TCResult {
|
) -> TCResult {
|
||||||
// SAFETY: see TCAnnotation docstring
|
// SAFETY: see TCAnnotation docstring
|
||||||
let ann = unsafe { TCAnnotation::take_from_arg(annotation, TCAnnotation::default()) };
|
let (entry, description) =
|
||||||
|
unsafe { TCAnnotation::take_from_arg(annotation, TCAnnotation::default()) };
|
||||||
wrap_mut(
|
wrap_mut(
|
||||||
task,
|
task,
|
||||||
|task| {
|
|task| {
|
||||||
task.add_annotation(ann)?;
|
let description = description.into_string()?;
|
||||||
|
task.add_annotation(Annotation { entry, description })?;
|
||||||
Ok(TCResult::Ok)
|
Ok(TCResult::Ok)
|
||||||
},
|
},
|
||||||
TCResult::Error,
|
TCResult::Error,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue