1use crate::silent_logs;
2use std::{
3 num::{FpCategory, NonZeroI32},
4 sync::LazyLock,
5};
6use tank::{AsValue, Entity, Error, Executor, Result, Value, expr};
7use tokio::sync::Mutex;
8
9static MUTEX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
10
11#[derive(Entity, PartialEq, Debug)]
12pub struct CustomValues {
13 #[tank(primary_key)]
14 pk: NonZeroI32,
15 #[tank(conversion_type = FpCategoryWrap)]
16 category: FpCategory,
17}
18pub struct FpCategoryWrap(pub FpCategory);
19impl AsValue for FpCategoryWrap {
20 fn as_empty_value() -> Value {
21 Value::Varchar(None)
22 }
23 fn as_value(self) -> Value {
24 format!("{:?}", self.0).as_value()
25 }
26
27 fn try_from_value(value: Value) -> Result<Self>
28 where
29 Self: Sized,
30 {
31 let make_error = || Error::msg(format!("Could not conver `{value:?}` to FpCategory"));
32 let Value::Varchar(Some(value), ..) = &value else {
33 return Err(make_error());
34 };
35 Ok(match value.as_ref() {
36 "Nan" => FpCategory::Nan,
37 "Infinite" => FpCategory::Infinite,
38 "Zero" => FpCategory::Zero,
39 "Subnormal" => FpCategory::Subnormal,
40 "Normal" => FpCategory::Normal,
41 _ => return Err(make_error()),
42 }
43 .into())
44 }
45}
46impl From<FpCategory> for FpCategoryWrap {
47 fn from(value: FpCategory) -> Self {
48 Self(value)
49 }
50}
51impl From<FpCategoryWrap> for FpCategory {
52 fn from(value: FpCategoryWrap) -> Self {
53 value.0
54 }
55}
56
57pub async fn custom(executor: &mut impl Executor) {
58 let _lock = MUTEX.lock().await;
59
60 silent_logs! {
62 CustomValues::drop_table(executor, true, false)
64 .await
65 .expect("Failed to drop SimpleNullFields table");
66 }
67 CustomValues::create_table(executor, true, true)
68 .await
69 .expect("Failed to create SimpleNullFields table");
70
71 CustomValues::insert_many(
73 executor,
74 &[
75 CustomValues {
76 pk: 50.try_into().unwrap(),
77 category: FpCategory::Subnormal,
78 },
79 CustomValues {
80 pk: 51.try_into().unwrap(),
81 category: FpCategory::Infinite,
82 },
83 ],
84 )
85 .await
86 .expect("Failed to insert values");
87 CustomValues {
88 pk: 52.try_into().unwrap(),
89 category: FpCategory::Nan,
90 }
91 .save(executor)
92 .await
93 .expect("Failed to save");
94 let value = CustomValues::find_one(executor, expr!(CustomValues::pk == 52))
95 .await
96 .expect("Failed to find");
97 assert_eq!(
98 value,
99 Some(CustomValues {
100 pk: 52.try_into().unwrap(),
101 category: FpCategory::Nan
102 })
103 );
104}