use cxx::{type_id, ExternType};
use std::fmt;
#[cxx::bridge]
mod ffi {
#[namespace = "Qt"]
unsafe extern "C++" {
include!("cxx-qt-lib/qt.h");
type DateFormat = crate::DateFormat;
}
unsafe extern "C++" {
include!("cxx-qt-lib/qtime.h");
include!("cxx-qt-lib/qstring.h");
type QTime = super::QTime;
type QString = crate::QString;
#[rust_name = "add_msecs"]
fn addMSecs(self: &QTime, ms: i32) -> QTime;
#[rust_name = "add_secs"]
fn addSecs(self: &QTime, s: i32) -> QTime;
fn hour(self: &QTime) -> i32;
#[rust_name = "is_null"]
fn isNull(self: &QTime) -> bool;
#[rust_name = "is_valid"]
fn isValid(self: &QTime) -> bool;
fn minute(self: &QTime) -> i32;
fn msec(self: &QTime) -> i32;
#[rust_name = "msecs_since_start_of_day"]
fn msecsSinceStartOfDay(self: &QTime) -> i32;
fn second(self: &QTime) -> i32;
#[rust_name = "set_hms"]
fn setHMS(self: &mut QTime, h: i32, m: i32, s: i32, ms: i32) -> bool;
#[rust_name = "format"]
fn toString(self: &QTime, format: &QString) -> QString;
#[rust_name = "format_enum"]
fn toString(self: &QTime, format: DateFormat) -> QString;
}
#[namespace = "rust::cxxqtlib1"]
unsafe extern "C++" {
#[doc(hidden)]
#[rust_name = "qtime_current_time"]
fn qtimeCurrentTime() -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_from_msecs_since_start_of_day"]
fn qtimeFromMSecsSinceStartOfDay(msecs: i32) -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_from_string"]
fn qtimeFromString(string: &QString, format: &QString) -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_from_string_enum"]
fn qtimeFromString(string: &QString, format: DateFormat) -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_msecs_to"]
fn qtimeMSecsTo(time: &QTime, t: QTime) -> i32;
#[doc(hidden)]
#[rust_name = "qtime_secs_to"]
fn qtimeSecsTo(time: &QTime, t: QTime) -> i32;
}
#[namespace = "rust::cxxqtlib1"]
unsafe extern "C++" {
include!("cxx-qt-lib/common.h");
#[doc(hidden)]
#[rust_name = "qtime_init_default"]
fn construct() -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_init"]
fn construct(h: i32, m: i32, s: i32, ms: i32) -> QTime;
#[doc(hidden)]
#[rust_name = "qtime_to_qstring"]
fn toQString(value: &QTime) -> QString;
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
#[repr(C)]
pub struct QTime {
mds: i32,
}
impl QTime {
pub fn current_time() -> Self {
ffi::qtime_current_time()
}
pub fn from_msecs_since_start_of_day(msecs: i32) -> Self {
ffi::qtime_from_msecs_since_start_of_day(msecs)
}
pub fn from_string(string: &ffi::QString, format: &ffi::QString) -> Self {
ffi::qtime_from_string(string, format)
}
pub fn from_string_enum(string: &ffi::QString, format: ffi::DateFormat) -> Self {
ffi::qtime_from_string_enum(string, format)
}
pub fn msecs_to(&self, t: Self) -> i32 {
ffi::qtime_msecs_to(self, t)
}
pub fn new(h: i32, m: i32, s: i32, ms: i32) -> Self {
ffi::qtime_init(h, m, s, ms)
}
pub fn secs_to(&self, t: Self) -> i32 {
ffi::qtime_secs_to(self, t)
}
}
impl Default for QTime {
fn default() -> Self {
ffi::qtime_init_default()
}
}
impl fmt::Display for QTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", ffi::qtime_to_qstring(self))
}
}
impl fmt::Debug for QTime {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{self}")
}
}
#[cfg(feature = "chrono")]
use chrono::Timelike;
#[cfg(feature = "chrono")]
impl From<chrono::NaiveTime> for QTime {
fn from(value: chrono::NaiveTime) -> Self {
let ms = (value.nanosecond() / 1_000_000) as i32;
QTime::new(
value.hour() as i32,
value.minute() as i32,
value.second() as i32 + (ms / 1_000),
ms % 1_000,
)
}
}
#[cfg(feature = "chrono")]
impl TryFrom<QTime> for chrono::NaiveTime {
type Error = &'static str;
fn try_from(value: QTime) -> Result<Self, Self::Error> {
chrono::NaiveTime::from_hms_milli_opt(
value.hour() as u32,
value.minute() as u32,
value.second() as u32,
value.msec() as u32,
)
.ok_or("invalid hour, minute, second and/or millisecond")
}
}
#[cfg(feature = "time")]
impl From<time::Time> for QTime {
fn from(value: time::Time) -> Self {
QTime::new(
value.hour() as i32,
value.minute() as i32,
value.second() as i32,
value.millisecond() as i32,
)
}
}
#[cfg(feature = "time")]
impl TryFrom<QTime> for time::Time {
type Error = time::error::ComponentRange;
fn try_from(value: QTime) -> Result<Self, Self::Error> {
time::Time::from_hms_milli(
value.hour() as u8,
value.minute() as u8,
value.second() as u8,
value.msec() as u16,
)
}
}
unsafe impl ExternType for QTime {
type Id = type_id!("QTime");
type Kind = cxx::kind::Trivial;
}
#[cfg(test)]
#[cfg(feature = "chrono")]
mod test_chrono {
use super::*;
#[test]
fn qtime_from_chrono_naive() {
let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 3, 4).unwrap();
let qtime = QTime::new(1, 2, 3, 4);
assert_eq!(QTime::from(naive), qtime);
}
#[test]
fn qtime_from_chrono_naive_leap_second() {
let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 3, 1_000).unwrap();
let qtime = QTime::new(1, 2, 4, 0);
assert_eq!(QTime::from(naive), qtime);
}
#[test]
fn qtime_to_chrono_naive() {
let naive = chrono::NaiveTime::from_hms_milli_opt(1, 2, 3, 4).unwrap();
let qtime = QTime::new(1, 2, 3, 4);
assert_eq!(chrono::NaiveTime::try_from(qtime).unwrap(), naive);
}
}
#[cfg(test)]
#[cfg(feature = "time")]
mod test_time {
use super::*;
#[test]
fn qtime_from_time_time() {
let time_time = time::Time::from_hms_milli(1, 2, 3, 4).unwrap();
let qtime = QTime::new(1, 2, 3, 4);
assert_eq!(QTime::from(time_time), qtime);
}
#[test]
fn qtime_to_time_time() {
let time_time = time::Time::from_hms_milli(1, 2, 3, 4).unwrap();
let qtime = QTime::new(1, 2, 3, 4);
assert_eq!(time::Time::try_from(qtime).unwrap(), time_time);
}
}