rune/core/object/
float.rs

1use super::{CloneIn, IntoObject};
2use crate::core::gc::{Block, GcHeap, GcState, Trace};
3use crate::derive_GcMoveable;
4use rune_macros::Trace;
5use std::fmt::{Debug, Display};
6
7/// A wrapper type for floats to work around issues with Eq. Rust only allows
8/// types to be used in match statements if they derive Eq. Even if you never
9/// actually use that field in a match. So we need a float wrapper that
10/// implements that trait.
11#[derive(PartialEq, Trace)]
12pub(crate) struct LispFloat(GcHeap<f64>);
13
14derive_GcMoveable!(LispFloat);
15
16impl std::ops::Deref for LispFloat {
17    type Target = f64;
18
19    fn deref(&self) -> &Self::Target {
20        &self.0
21    }
22}
23
24impl LispFloat {
25    pub fn new(float: f64, constant: bool) -> Self {
26        LispFloat(GcHeap::new(float, constant))
27    }
28}
29
30impl Trace for f64 {
31    fn trace(&self, _: &mut GcState) {}
32}
33
34impl Eq for LispFloat {}
35
36impl<'new> CloneIn<'new, &'new LispFloat> for LispFloat {
37    fn clone_in<const C: bool>(&self, bk: &'new Block<C>) -> super::Gc<&'new Self> {
38        (**self).into_obj(bk)
39    }
40}
41
42impl Display for LispFloat {
43    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
44        let float = **self;
45        if float.fract() == 0.0_f64 {
46            write!(f, "{float:.1}")
47        } else {
48            write!(f, "{float}")
49        }
50    }
51}
52
53impl Debug for LispFloat {
54    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
55        write!(f, "{self}")
56    }
57}