#![cfg(feature = "rust_decimal")]
use alloc::string::String;
use rust_decimal::Decimal;
use crate::{
Def, Facet, OxPtrConst, OxPtrUninit, ParseError, PtrConst, Shape, ShapeBuilder, TryFromOutcome,
Type, UserType, VTableIndirect,
};
unsafe fn try_from_decimal(
target: OxPtrUninit,
src_shape: &'static Shape,
src: PtrConst,
) -> TryFromOutcome {
unsafe {
if src_shape.id == <&str as Facet>::SHAPE.id {
let source_str: &str = src.get::<&str>();
match source_str.parse::<Decimal>() {
Ok(val) => {
target.put(val);
TryFromOutcome::Converted
}
Err(_) => TryFromOutcome::Failed("Decimal parsing failed".into()),
}
}
else if src_shape.id == <String as Facet>::SHAPE.id {
let source_str = src.read::<String>();
match source_str.parse::<Decimal>() {
Ok(val) => {
target.put(val);
TryFromOutcome::Converted
}
Err(_) => TryFromOutcome::Failed("Decimal parsing failed".into()),
}
}
else {
TryFromOutcome::Unsupported
}
}
}
unsafe fn parse_decimal(s: &str, target: OxPtrUninit) -> Option<Result<(), ParseError>> {
unsafe {
let parsed = s
.parse::<Decimal>()
.map_err(|_| ParseError::from_str("Decimal parsing failed"));
Some(match parsed {
Ok(val) => {
target.put(val);
Ok(())
}
Err(e) => Err(e),
})
}
}
unsafe fn display_decimal(
source: OxPtrConst,
f: &mut core::fmt::Formatter<'_>,
) -> Option<core::fmt::Result> {
unsafe {
let decimal = source.get::<Decimal>();
Some(write!(f, "{decimal}"))
}
}
unsafe fn partial_eq_decimal(a: OxPtrConst, b: OxPtrConst) -> Option<bool> {
unsafe {
let a = a.get::<Decimal>();
let b = b.get::<Decimal>();
Some(a == b)
}
}
unsafe fn partial_ord_decimal(a: OxPtrConst, b: OxPtrConst) -> Option<Option<core::cmp::Ordering>> {
unsafe {
let a = a.get::<Decimal>();
let b = b.get::<Decimal>();
Some(a.partial_cmp(b))
}
}
unsafe fn ord_decimal(a: OxPtrConst, b: OxPtrConst) -> Option<core::cmp::Ordering> {
unsafe {
let a = a.get::<Decimal>();
let b = b.get::<Decimal>();
Some(a.cmp(b))
}
}
unsafe fn hash_decimal(value: OxPtrConst, state: &mut crate::HashProxy<'_>) -> Option<()> {
unsafe {
use core::hash::Hash;
let decimal = value.get::<Decimal>();
decimal.hash(state);
Some(())
}
}
unsafe fn debug_decimal(
source: OxPtrConst,
f: &mut core::fmt::Formatter<'_>,
) -> Option<core::fmt::Result> {
unsafe {
let decimal = source.get::<Decimal>();
Some(write!(f, "{decimal:?}"))
}
}
const DECIMAL_VTABLE: VTableIndirect = VTableIndirect {
display: Some(display_decimal),
debug: Some(debug_decimal),
try_from: Some(try_from_decimal),
parse: Some(parse_decimal),
partial_eq: Some(partial_eq_decimal),
partial_cmp: Some(partial_ord_decimal),
cmp: Some(ord_decimal),
hash: Some(hash_decimal),
..VTableIndirect::EMPTY
};
unsafe impl Facet<'_> for Decimal {
const SHAPE: &'static Shape = &const {
ShapeBuilder::for_sized::<Decimal>("Decimal")
.module_path("rust_decimal")
.ty(Type::User(UserType::Opaque))
.def(Def::Scalar)
.vtable_indirect(&DECIMAL_VTABLE)
.eq()
.copy()
.send()
.sync()
.build()
};
}