#[cfg(not(PyPy))]
use crate::PyCapsule_Import;
#[cfg(GraalPy)]
use crate::{PyLong_AsLong, PyLong_Check, PyObject_GetAttrString, Py_DecRef};
use crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE};
#[cfg(not(GraalPy))]
use std::os::raw::c_char;
use std::os::raw::c_int;
use std::ptr;
use std::sync::Once;
use std::{cell::UnsafeCell, ffi::CStr};
#[cfg(not(any(PyPy, GraalPy)))]
use {crate::Py_hash_t, std::os::raw::c_uchar};
const _PyDateTime_DATE_DATASIZE: usize = 4;
const _PyDateTime_TIME_DATASIZE: usize = 6;
const _PyDateTime_DATETIME_DATASIZE: usize = 10;
#[repr(C)]
#[derive(Debug)]
pub struct PyDateTime_Delta {
pub ob_base: PyObject,
#[cfg(not(any(PyPy, GraalPy)))]
pub hashcode: Py_hash_t,
#[cfg(not(GraalPy))]
pub days: c_int,
#[cfg(not(GraalPy))]
pub seconds: c_int,
#[cfg(not(GraalPy))]
pub microseconds: c_int,
}
#[cfg(not(any(PyPy, GraalPy)))]
#[repr(C)]
#[derive(Debug)]
pub struct _PyDateTime_BaseTime {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub hastzinfo: c_char,
pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
}
#[repr(C)]
#[derive(Debug)]
pub struct PyDateTime_Time {
pub ob_base: PyObject,
#[cfg(not(any(PyPy, GraalPy)))]
pub hashcode: Py_hash_t,
#[cfg(not(GraalPy))]
pub hastzinfo: c_char,
#[cfg(not(any(PyPy, GraalPy)))]
pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
#[cfg(not(any(PyPy, GraalPy)))]
pub fold: c_uchar,
#[cfg(not(GraalPy))]
pub tzinfo: *mut PyObject,
}
#[repr(C)]
#[derive(Debug)]
pub struct PyDateTime_Date {
pub ob_base: PyObject,
#[cfg(not(any(PyPy, GraalPy)))]
pub hashcode: Py_hash_t,
#[cfg(not(any(PyPy, GraalPy)))]
pub hastzinfo: c_char,
#[cfg(not(any(PyPy, GraalPy)))]
pub data: [c_uchar; _PyDateTime_DATE_DATASIZE],
}
#[cfg(not(any(PyPy, GraalPy)))]
#[repr(C)]
#[derive(Debug)]
pub struct _PyDateTime_BaseDateTime {
pub ob_base: PyObject,
pub hashcode: Py_hash_t,
pub hastzinfo: c_char,
pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
}
#[repr(C)]
#[derive(Debug)]
pub struct PyDateTime_DateTime {
pub ob_base: PyObject,
#[cfg(not(any(PyPy, GraalPy)))]
pub hashcode: Py_hash_t,
#[cfg(not(GraalPy))]
pub hastzinfo: c_char,
#[cfg(not(any(PyPy, GraalPy)))]
pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
#[cfg(not(any(PyPy, GraalPy)))]
pub fold: c_uchar,
#[cfg(not(GraalPy))]
pub tzinfo: *mut PyObject,
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
let data = (*(o as *mut PyDateTime_Date)).data;
c_int::from(data[0]) << 8 | c_int::from(data[1])
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
let data = (*(o as *mut PyDateTime_Date)).data;
c_int::from(data[2])
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
let data = (*(o as *mut PyDateTime_Date)).data;
c_int::from(data[3])
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _PyDateTime_GET_HOUR {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 0])
};
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _PyDateTime_GET_MINUTE {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 1])
};
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _PyDateTime_GET_SECOND {
($o: expr, $offset:expr) => {
c_int::from((*$o).data[$offset + 2])
};
}
#[cfg(not(any(PyPy, GraalPy)))]
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(not(any(PyPy, GraalPy)))]
macro_rules! _PyDateTime_GET_FOLD {
($o: expr) => {
(*$o).fold
};
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _PyDateTime_GET_TZINFO {
($o: expr) => {
if (*$o).hastzinfo != 0 {
(*$o).tzinfo
} else {
$crate::Py_None()
}
};
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
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(any(PyPy, GraalPy)))]
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(any(PyPy, GraalPy)))]
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(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)
}
#[cfg(not(any(PyPy, GraalPy)))]
#[inline]
pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _access_field {
($obj:expr, $type: ident, $field:ident) => {
(*($obj as *mut $type)).$field
};
}
#[cfg(not(any(PyPy, GraalPy)))]
macro_rules! _access_delta_field {
($obj:expr, $field:ident) => {
_access_field!($obj, PyDateTime_Delta, $field)
};
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, days)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, seconds)
}
#[inline]
#[cfg(not(any(PyPy, GraalPy)))]
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
_access_delta_field!(o, microseconds)
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn _get_attr(obj: *mut PyObject, field: &std::ffi::CStr) -> c_int {
let result = PyObject_GetAttrString(obj, field.as_ptr());
Py_DecRef(result); if PyLong_Check(result) == 1 {
PyLong_AsLong(result) as c_int
} else {
0
}
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("year"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("month"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("day"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("hour"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("minute"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("second"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("microsecond"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("fold"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
let res = PyObject_GetAttrString(o, c_str!("tzinfo").as_ptr().cast());
Py_DecRef(res); res
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("hour"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("minute"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("second"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("microsecond"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("fold"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
let res = PyObject_GetAttrString(o, c_str!("tzinfo").as_ptr().cast());
Py_DecRef(res); res
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("days"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("seconds"))
}
#[inline]
#[cfg(GraalPy)]
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
_get_attr(o, c_str!("microseconds"))
}
#[cfg(PyPy)]
extern "C" {
#[link_name = "PyPyDateTime_GET_YEAR"]
pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_MONTH"]
pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_DAY"]
pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DATE_GET_HOUR"]
pub fn PyDateTime_DATE_GET_HOUR(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_DATE_GET_MICROSECOND"]
pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_GET_FOLD"]
pub fn PyDateTime_DATE_GET_FOLD(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_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 = "PyPyDateTime_TIME_GET_MICROSECOND"]
pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_TIME_GET_FOLD"]
pub fn PyDateTime_TIME_GET_FOLD(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_SECONDS"]
pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int;
#[link_name = "PyPyDateTime_DELTA_GET_MICROSECONDS"]
pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int;
}
#[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,
pub TimeZone_UTC: *mut PyObject,
pub Date_FromDate: unsafe extern "C" fn(
year: c_int,
month: c_int,
day: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
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,
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,
pub Delta_FromDelta: unsafe extern "C" fn(
days: c_int,
seconds: c_int,
microseconds: c_int,
normalize: c_int,
cls: *mut PyTypeObject,
) -> *mut PyObject,
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,
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,
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,
}
unsafe impl Sync for PyDateTime_CAPI {}
pub const PyDateTime_CAPSULE_NAME: &CStr = c_str!("datetime.datetime_CAPI");
#[inline]
pub unsafe fn PyDateTimeAPI() -> *mut PyDateTime_CAPI {
*PyDateTimeAPI_impl.ptr.get()
}
pub unsafe fn PyDateTime_IMPORT() {
if !PyDateTimeAPI_impl.once.is_completed() {
#[cfg(PyPy)]
let py_datetime_c_api = PyDateTime_Import();
#[cfg(not(PyPy))]
let py_datetime_c_api =
PyCapsule_Import(PyDateTime_CAPSULE_NAME.as_ptr(), 1) as *mut PyDateTime_CAPI;
if py_datetime_c_api.is_null() {
return;
}
PyDateTimeAPI_impl.once.call_once(|| {
*PyDateTimeAPI_impl.ptr.get() = py_datetime_c_api;
});
}
}
#[inline]
pub unsafe fn PyDateTime_TimeZone_UTC() -> *mut PyObject {
(*PyDateTimeAPI()).TimeZone_UTC
}
#[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
}
pub unsafe fn PyTimeZone_FromOffset(offset: *mut PyObject) -> *mut PyObject {
((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, std::ptr::null_mut())
}
pub unsafe fn PyTimeZone_FromOffsetAndName(
offset: *mut PyObject,
name: *mut PyObject,
) -> *mut PyObject {
((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, name)
}
#[cfg(not(PyPy))]
pub unsafe fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
let f = (*PyDateTimeAPI()).DateTime_FromTimestamp;
f((*PyDateTimeAPI()).DateTimeType, args, std::ptr::null_mut())
}
#[cfg(not(PyPy))]
pub unsafe fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject {
let f = (*PyDateTimeAPI()).Date_FromTimestamp;
f((*PyDateTimeAPI()).DateType, args)
}
#[cfg(PyPy)]
extern "C" {
#[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;
}
#[cfg(PyPy)]
extern "C" {
#[link_name = "_PyPyDateTime_Import"]
pub fn PyDateTime_Import() -> *mut PyDateTime_CAPI;
}
struct PyDateTimeAPISingleton {
once: Once,
ptr: UnsafeCell<*mut PyDateTime_CAPI>,
}
unsafe impl Sync for PyDateTimeAPISingleton {}
static PyDateTimeAPI_impl: PyDateTimeAPISingleton = PyDateTimeAPISingleton {
once: Once::new(),
ptr: UnsafeCell::new(ptr::null_mut()),
};