#![cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
use crate::ffi::Py_hash_t;
use crate::ffi::{PyObject, PyTypeObject};
use crate::ffi::{PyObject_TypeCheck, Py_TYPE};
use crate::once_cell::GILOnceCell;
use crate::Python;
use std::ops::Deref;
use std::os::raw::{c_char, c_int, c_uchar};
#[cfg(not(PyPy))]
use {crate::ffi::PyCapsule_Import, std::ffi::CString};
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_CAPI {
pub DateType: *mut PyTypeObject,
pub DateTimeType: *mut PyTypeObject,
pub TimeType: *mut PyTypeObject,
pub DeltaType: *mut PyTypeObject,
pub TZInfoType: *mut PyTypeObject,
#[cfg(Py_3_7)]
pub TimeZone_UTC: *mut PyObject,
#[cfg_attr(PyPy, link_name = "_PyPyDate_FromDate")]
pub Date_FromDate: unsafe extern "C" fn(
year: c_int,
month: c_int,
day: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
#[cfg_attr(PyPy, link_name = "_PyPyDateTime_FromDateAndTime")]
pub DateTime_FromDateAndTime: unsafe extern "C" fn(
year: c_int,
month: c_int,
day: c_int,
hour: c_int,
minute: c_int,
second: c_int,
microsecond: c_int,
tzinfo: *mut PyObject,
cls: *mut PyTypeObject,
) -> *mut PyObject,
#[cfg_attr(PyPy, link_name = "_PyPyTime_FromTime")]
pub Time_FromTime: unsafe extern "C" fn(
hour: c_int,
minute: c_int,
second: c_int,
microsecond: c_int,
tzinfo: *mut PyObject,
cls: *mut PyTypeObject,
) -> *mut PyObject,
#[cfg_attr(PyPy, link_name = "_PyPyDelta_FromDelta")]
pub Delta_FromDelta: unsafe extern "C" fn(
days: c_int,
seconds: c_int,
microseconds: c_int,
normalize: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
#[cfg(Py_3_7)]
pub TimeZone_FromTimeZone:
unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,
pub DateTime_FromTimestamp: unsafe extern "C" fn(
cls: *mut PyTypeObject,
args: *mut PyObject,
kwargs: *mut PyObject,
) -> *mut PyObject,
pub Date_FromTimestamp:
unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,
#[cfg(Py_3_6)]
pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn(
year: c_int,
month: c_int,
day: c_int,
hour: c_int,
minute: c_int,
second: c_int,
microsecond: c_int,
tzinfo: *mut PyObject,
fold: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
#[cfg(Py_3_6)]
pub Time_FromTimeAndFold: unsafe extern "C" fn(
hour: c_int,
minute: c_int,
second: c_int,
microsecond: c_int,
tzinfo: *mut PyObject,
fold: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
}
#[cfg(PyPy)]
extern "C" {
#[link_name = "_PyPyDateTime_Import"]
pub fn PyDateTime_Import() -> &'static PyDateTime_CAPI;
#[link_name = "PyPyDateTime_DATE_GET_HOUR"]
pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DATE_GET_MICROSECOND"]
pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DATE_GET_MINUTE"]
pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DATE_GET_SECOND"]
pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DELTA_GET_DAYS"]
pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"]
pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DELTA_GET_SECONDS"]
pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_DAY"]
pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_MONTH"]
pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_YEAR"]
pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_TIME_GET_HOUR"]
pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_TIME_GET_MICROSECOND"]
pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_TIME_GET_MINUTE"]
pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_TIME_GET_SECOND"]
pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDate_FromTimestamp"]
pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
#[link_name = "PyPyDateTime_FromTimestamp"]
pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject;
}
const _PyDateTime_DATE_DATASIZE: usize = 4;
const _PyDateTime_TIME_DATASIZE: usize = 6;
const _PyDateTime_DATETIME_DATASIZE: usize = 10;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_Date {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub hastzinfo: c_char,
pub data: [c_uchar; _PyDateTime_DATE_DATASIZE],
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_Time {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub hastzinfo: c_char,
pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
#[cfg(Py_3_6)]
pub fold: c_uchar,
pub tzinfo: *mut PyObject,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_DateTime {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub hastzinfo: c_char,
pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
#[cfg(Py_3_6)]
pub fold: c_uchar,
pub tzinfo: *mut PyObject,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PyDateTime_Delta {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub days: c_int,
pub seconds: c_int,
pub microseconds: c_int,
}
unsafe impl Sync for PyDateTime_CAPI {}
static PY_DATETIME_API: GILOnceCell<&'static PyDateTime_CAPI> = GILOnceCell::new();
#[derive(Debug)]
pub struct PyDateTimeAPI {
__private_field: (),
}
pub static PyDateTimeAPI: PyDateTimeAPI = PyDateTimeAPI {
__private_field: (),
};
impl Deref for PyDateTimeAPI {
type Target = PyDateTime_CAPI;
fn deref(&self) -> &'static PyDateTime_CAPI {
unsafe { PyDateTime_IMPORT() }
}
}
#[inline]
pub unsafe fn PyDateTime_IMPORT() -> &'static PyDateTime_CAPI {
let py = Python::assume_gil_acquired();
PY_DATETIME_API.get_or_init(py, || {
#[cfg(PyPy)]
let py_datetime_c_api = PyDateTime_Import();
#[cfg(not(PyPy))]
let py_datetime_c_api = {
let PyDateTime_CAPSULE_NAME = CString::new("datetime.datetime_CAPI").unwrap();
&*(PyCapsule_Import(PyDateTime_CAPSULE_NAME.as_ptr(), 1) as *const PyDateTime_CAPI)
};
py_datetime_c_api
})
}
#[inline]
pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.DateType) as c_int
}
#[inline]
pub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == PyDateTimeAPI.DateType) as c_int
}
#[inline]
pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType) as c_int
}
#[inline]
pub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == PyDateTimeAPI.DateTimeType) as c_int
}
#[inline]
pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.TimeType) as c_int
}
#[inline]
pub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == PyDateTimeAPI.TimeType) as c_int
}
#[inline]
pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType) as c_int
}
#[inline]
pub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == PyDateTimeAPI.DeltaType) as c_int
}
#[inline]
pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {
PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType) as c_int
}
#[inline]
pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {
(Py_TYPE(op) == PyDateTimeAPI.TZInfoType) as c_int
}
#[cfg(not(PyPy))]
macro_rules! _access_field {
($obj:expr, $type: ident, $field:tt) => {
(*($obj as *mut $type)).$field
};
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
let d = *(o as *mut PyDateTime_Date);
c_int::from(d.data[0]) << 8 | c_int::from(d.data[1])
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
let d = *(o as *mut PyDateTime_Date);
c_int::from(d.data[2])
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
let d = *(o as *mut PyDateTime_Date);
c_int::from(d.data[3])
}
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_HOUR {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 0])
};
}
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_MINUTE {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 1])
};
}
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_SECOND {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 2])
};
}
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_MICROSECOND {
($o: expr, $offset:expr) => {
(c_int::from((*$o).data[$offset + 3]) << 16)
| (c_int::from((*$o).data[$offset + 4]) << 8)
| (c_int::from((*$o).data[$offset + 5]))
};
}
#[cfg(Py_3_6)]
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_FOLD {
($o: expr) => {
(*$o).fold
};
}
#[cfg(not(PyPy))]
macro_rules! _PyDateTime_GET_TZINFO {
($o: expr) => {
(*$o).tzinfo
};
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
}
#[cfg(Py_3_6)]
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)
}
#[cfg(all(Py_3_6, not(PyPy)))]
#[inline]
pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)
}
#[cfg(not(PyPy))]
macro_rules! _access_delta_field {
($obj:expr, $field:tt) => {
_access_field!($obj, PyDateTime_Delta, $field)
};
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, days)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, seconds)
}
#[inline]
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, microseconds)
}