use std::{
ffi::{c_void, CStr, CString},
fmt::Debug,
hash::Hash,
ptr,
str::FromStr,
};
use chrono::{DateTime, TimeZone};
use super::tnumber::{impl_meos_enum, impl_temporal_for_tnumber, TNumber};
use crate::{
boxes::TBox,
collections::{
base::{impl_collection, Collection, Span, SpanSet},
datetime::{TsTzSpan, TsTzSpanSet},
number::FloatSpanSet,
},
errors::ParseError,
factory, impl_from_str,
temporal::{
interpolation::TInterpolation,
tbool::{TBool, TBoolInstant, TBoolSequence, TBoolSequenceSet},
temporal::{
impl_always_and_ever_value_equality_functions, impl_ordered_temporal_functions,
impl_simple_traits_for_temporal, OrderedTemporal, SimplifiableTemporal, Temporal,
},
tinstant::TInstant,
tsequence::TSequence,
tsequence_set::TSequenceSet,
},
utils::to_meos_timestamp,
MeosEnum,
};
macro_rules! impl_debug {
($type:ty) => {
impl Debug for $type {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let out_str = unsafe { meos_sys::tfloat_out(self.inner(), 5) };
let c_str = unsafe { CStr::from_ptr(out_str) };
let string = c_str.to_str().map_err(|_| std::fmt::Error)?;
let result = f.write_str(string);
unsafe { libc::free(out_str.cast::<c_void>()) };
result
}
}
};
}
#[derive(Debug)]
pub enum TFloat {
Instant(TFloatInstant),
Sequence(TFloatSequence),
SequenceSet(TFloatSequenceSet),
}
impl_from_str!(TFloat);
impl MeosEnum for TFloat {
fn from_instant(inner: *mut meos_sys::TInstant) -> Self {
Self::Instant(TFloatInstant {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
})
}
fn from_sequence(inner: *mut meos_sys::TSequence) -> Self {
Self::Sequence(TFloatSequence {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
})
}
fn from_sequence_set(inner: *mut meos_sys::TSequenceSet) -> Self {
Self::SequenceSet(TFloatSequenceSet {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
})
}
fn from_mfjson(mfjson: &str) -> Self {
let cstr = CString::new(mfjson).unwrap();
factory::<Self>(unsafe { meos_sys::tfloat_from_mfjson(cstr.as_ptr()) })
}
}
pub trait TFloatTrait:
TNumber<Type = f64, TI = TFloatInstant, TS = TFloatSequence, TSS = TFloatSequenceSet, TBB = TBox>
{
fn shift_scale_value(&self, shift: Option<Self::Type>, width: Option<Self::Type>) -> Self {
let d = shift.unwrap_or_default();
let w = width.unwrap_or_default();
let modified = unsafe { meos_sys::tfloat_shift_scale_value(self.inner(), d, w) };
Self::from_inner_as_temporal(modified)
}
}
pub struct TFloatInstant {
_inner: ptr::NonNull<meos_sys::TInstant>,
}
impl TInstant for TFloatInstant {
fn from_inner(inner: *mut meos_sys::TInstant) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
fn inner_as_tinstant(&self) -> *const meos_sys::TInstant {
self._inner.as_ptr()
}
fn from_value_and_timestamp<Tz: TimeZone>(value: Self::Type, timestamp: DateTime<Tz>) -> Self {
Self::from_inner(unsafe { meos_sys::tfloatinst_make(value, to_meos_timestamp(×tamp)) })
}
}
impl TFloatTrait for TFloatInstant {}
impl_temporal_for_tnumber!(TFloatInstant, Instant, f64, Float);
impl_debug!(TFloatInstant);
impl SimplifiableTemporal for TFloatInstant {}
impl<Tz: TimeZone> From<(f64, DateTime<Tz>)> for TFloatInstant {
fn from((v, t): (f64, DateTime<Tz>)) -> Self {
Self::from_value_and_timestamp(v, t)
}
}
pub struct TFloatSequence {
_inner: ptr::NonNull<meos_sys::TSequence>,
}
impl TFloatSequence {
pub fn from_value_and_tstz_span<Tz: TimeZone>(
value: f64,
time_span: &TsTzSpan,
interpolation: TInterpolation,
) -> Self {
Self::from_inner(unsafe {
meos_sys::tfloatseq_from_base_tstzspan(value, time_span.inner(), interpolation as u32)
})
}
}
impl TSequence for TFloatSequence {
fn from_inner(inner: *mut meos_sys::TSequence) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
fn inner_mut_as_tsequence(&self) -> *mut meos_sys::TSequence {
self._inner.as_ptr()
}
}
impl TFloatTrait for TFloatSequence {}
impl_temporal_for_tnumber!(TFloatSequence, Sequence, f64, Float);
impl_debug!(TFloatSequence);
impl SimplifiableTemporal for TFloatSequence {}
impl FromIterator<TFloatInstant> for TFloatSequence {
fn from_iter<T: IntoIterator<Item = TFloatInstant>>(iter: T) -> Self {
let vec: Vec<TFloatInstant> = iter.into_iter().collect();
Self::new(&vec, TInterpolation::Linear)
}
}
impl<'a> FromIterator<&'a TFloatInstant> for TFloatSequence {
fn from_iter<T: IntoIterator<Item = &'a TFloatInstant>>(iter: T) -> Self {
let vec: Vec<&TFloatInstant> = iter.into_iter().collect();
Self::new(&vec, TInterpolation::Linear)
}
}
pub struct TFloatSequenceSet {
_inner: ptr::NonNull<meos_sys::TSequenceSet>,
}
impl TFloatSequenceSet {
pub fn from_value_and_tstz_span_set<Tz: TimeZone>(
value: f64,
time_span_set: &TsTzSpanSet,
interpolation: TInterpolation,
) -> Self {
Self::from_inner(unsafe {
meos_sys::tfloatseqset_from_base_tstzspanset(
value,
time_span_set.inner(),
interpolation as u32,
)
})
}
}
impl TSequenceSet for TFloatSequenceSet {
fn from_inner(inner: *mut meos_sys::TSequenceSet) -> Self {
Self {
_inner: ptr::NonNull::new(inner).expect("Null pointers not allowed"),
}
}
}
impl TFloatTrait for TFloatSequenceSet {}
impl_temporal_for_tnumber!(TFloatSequenceSet, SequenceSet, f64, Float);
impl_debug!(TFloatSequenceSet);
impl SimplifiableTemporal for TFloatSequenceSet {}
impl From<TFloatInstant> for TFloat {
fn from(value: TFloatInstant) -> Self {
TFloat::Instant(value)
}
}
impl From<TFloatSequence> for TFloat {
fn from(value: TFloatSequence) -> Self {
TFloat::Sequence(value)
}
}
impl From<TFloatSequenceSet> for TFloat {
fn from(value: TFloatSequenceSet) -> Self {
TFloat::SequenceSet(value)
}
}
impl TryFrom<TFloat> for TFloatInstant {
type Error = ParseError;
fn try_from(value: TFloat) -> Result<Self, Self::Error> {
if let TFloat::Instant(new_value) = value {
Ok(new_value)
} else {
Err(ParseError)
}
}
}
impl TryFrom<TFloat> for TFloatSequence {
type Error = ParseError;
fn try_from(value: TFloat) -> Result<Self, Self::Error> {
if let TFloat::Sequence(new_value) = value {
Ok(new_value)
} else {
Err(ParseError)
}
}
}
impl TryFrom<TFloat> for TFloatSequenceSet {
type Error = ParseError;
fn try_from(value: TFloat) -> Result<Self, Self::Error> {
if let TFloat::SequenceSet(new_value) = value {
Ok(new_value)
} else {
Err(ParseError)
}
}
}
impl_meos_enum!(TFloat, f64, Float);