• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

facet-rs / facet / 15487210020

06 Jun 2025 09:19AM UTC coverage: 59.521% (+0.06%) from 59.46%
15487210020

push

github

fasterthanlime
Introduced sized/unsized ValueVTable variants

Co-Authored-By: Asger Hautop Drewsen <asger@tyilo.com>

375 of 811 new or added lines in 32 files covered. (46.24%)

9 existing lines in 4 files now uncovered.

10537 of 17703 relevant lines covered (59.52%)

150.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

20.0
/facet-core/src/impls_ordered_float.rs
1
use crate::{
2
    Def, Facet, PtrConst, PtrMut, PtrUninit, Repr, ScalarAffinity, ScalarDef, Shape, StructType,
3
    TryBorrowInnerError, TryFromError, TryIntoInnerError, Type, UserType, ValueVTable,
4
    field_in_type, value_vtable,
5
};
6
use ordered_float::{NotNan, OrderedFloat};
7

8
macro_rules! impl_facet_for_ordered_float_and_notnan {
9
    ($float:ty) => {
10
        unsafe impl<'a> Facet<'a> for OrderedFloat<$float> {
11
            const VTABLE: &'static ValueVTable = &const {
12
                // Define conversion functions for transparency
13
                unsafe fn try_from<'shape, 'dst>(
3✔
14
                    src_ptr: PtrConst<'_>,
3✔
15
                    src_shape: &'shape Shape<'shape>,
3✔
16
                    dst: PtrUninit<'dst>,
3✔
17
                ) -> Result<PtrMut<'dst>, TryFromError<'shape>> {
3✔
18
                    if src_shape == <$float as Facet>::SHAPE {
3✔
19
                        // Get the inner value and wrap as OrderedFloat
20
                        let value = unsafe { src_ptr.get::<$float>() };
2✔
21
                        let ord = OrderedFloat(*value);
2✔
22
                        Ok(unsafe { dst.put(ord) })
2✔
23
                    } else {
NEW
24
                        let inner_try_from =
×
25
                            (<$float as Facet>::SHAPE.vtable.sized().unwrap().try_from)().ok_or(
1✔
26
                                TryFromError::UnsupportedSourceShape {
1✔
27
                                    src_shape,
1✔
28
                                    expected: &[<$float as Facet>::SHAPE],
1✔
29
                                },
1✔
30
                            )?;
1✔
31
                        // fallback to inner's try_from
32
                        // This relies on the fact that `dst` is the same size as `OrderedFloat<$float>`
33
                        // which should be true because `OrderedFloat` is `repr(transparent)`
34
                        let inner_result = unsafe { (inner_try_from)(src_ptr, src_shape, dst) };
×
35
                        match inner_result {
×
36
                            Ok(result) => {
×
37
                                // After conversion to inner type, wrap as OrderedFloat
38
                                let value = unsafe { result.read::<$float>() };
×
39
                                let ord = OrderedFloat(value);
×
40
                                Ok(unsafe { dst.put(ord) })
×
41
                            }
42
                            Err(e) => Err(e),
×
43
                        }
44
                    }
45
                }
3✔
46

47
                // Conversion back to inner float type
48
                unsafe fn try_into_inner<'dst>(
×
49
                    src_ptr: PtrMut<'_>,
×
50
                    dst: PtrUninit<'dst>,
×
51
                ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
52
                    let v = unsafe { src_ptr.read::<OrderedFloat<$float>>() };
×
53
                    Ok(unsafe { dst.put(v.0) })
×
54
                }
×
55

56
                // Borrow inner float type
57
                unsafe fn try_borrow_inner(
×
58
                    src_ptr: PtrConst<'_>,
×
59
                ) -> Result<PtrConst<'_>, TryBorrowInnerError> {
×
60
                    let v = unsafe { src_ptr.get::<OrderedFloat<$float>>() };
×
61
                    Ok(PtrConst::new((&v.0) as *const $float as *const u8))
×
62
                }
×
63

64
                let mut vtable =
65
                    value_vtable!((), |f, _opts| write!(f, "{}", Self::SHAPE.type_identifier));
5✔
66
                {
67
                    let vtable = vtable.sized_mut().unwrap();
NEW
68
                    vtable.parse = || {
×
69
                        // `OrderedFloat` is `repr(transparent)`
NEW
70
                        (<$float as Facet>::SHAPE.vtable.sized().unwrap().parse)()
×
NEW
71
                    };
×
72
                    vtable.try_from = || Some(try_from);
7✔
NEW
73
                    vtable.try_into_inner = || Some(try_into_inner);
×
NEW
74
                    vtable.try_borrow_inner = || Some(try_borrow_inner);
×
75
                }
76
                vtable
77
            };
78

79
            const SHAPE: &'static Shape<'static> = &const {
80
                fn inner_shape() -> &'static Shape<'static> {
6✔
81
                    <$float as Facet>::SHAPE
6✔
82
                }
6✔
83

84
                Shape::builder_for_sized::<Self>()
85
                    .type_identifier("OrderedFloat")
86
                    .ty(Type::User(UserType::Struct(
87
                        StructType::builder()
88
                            .repr(Repr::transparent())
89
                            .fields(&const { [field_in_type!(Self, 0)] })
90
                            .kind(crate::StructKind::Tuple)
91
                            .build(),
92
                    )))
93
                    .def(Def::Scalar(
94
                        ScalarDef::builder()
95
                            // Affinity: use number affinity as inner's
96
                            .affinity(&const { ScalarAffinity::opaque().build() })
97
                            .build(),
98
                    ))
99
                    .inner(inner_shape)
100
                    .build()
101
            };
102
        }
103

104
        unsafe impl<'a> Facet<'a> for NotNan<$float> {
105
            const VTABLE: &'static ValueVTable = &const {
106
                // Conversion from inner float type to NotNan<$float>
107
                unsafe fn try_from<'shape, 'dst>(
×
108
                    src_ptr: PtrConst<'_>,
×
109
                    src_shape: &'shape Shape<'shape>,
×
110
                    dst: PtrUninit<'dst>,
×
111
                ) -> Result<PtrMut<'dst>, TryFromError<'shape>> {
×
112
                    if src_shape == <$float as Facet>::SHAPE {
×
113
                        // Get the inner value and check that it's not NaN
114
                        let value = unsafe { *src_ptr.get::<$float>() };
×
115
                        let nn =
×
116
                            NotNan::new(value).map_err(|_| TryFromError::Generic("was NaN"))?;
×
117
                        Ok(unsafe { dst.put(nn) })
×
118
                    } else {
NEW
119
                        let inner_try_from =
×
NEW
120
                            (<$float as Facet>::SHAPE.vtable.sized().unwrap().try_from)().ok_or(
×
NEW
121
                                TryFromError::UnsupportedSourceShape {
×
NEW
122
                                    src_shape,
×
NEW
123
                                    expected: &[<$float as Facet>::SHAPE],
×
NEW
124
                                },
×
NEW
125
                            )?;
×
126

127
                        // fallback to inner's try_from
128
                        // This relies on the fact that `dst` is the same size as `NotNan<$float>`
129
                        // which should be true because `NotNan` is `repr(transparent)`
130
                        let inner_result = unsafe { (inner_try_from)(src_ptr, src_shape, dst) };
×
131
                        match inner_result {
×
132
                            Ok(result) => {
×
133
                                // After conversion to inner type, wrap as NotNan
134
                                let value = unsafe { *result.get::<$float>() };
×
135
                                let nn = NotNan::new(value)
×
136
                                    .map_err(|_| TryFromError::Generic("was NaN"))?;
×
137
                                Ok(unsafe { dst.put(nn) })
×
138
                            }
139
                            Err(e) => Err(e),
×
140
                        }
141
                    }
142
                }
×
143

144
                // Conversion back to inner float type
145
                unsafe fn try_into_inner<'dst>(
×
146
                    src_ptr: PtrMut<'_>,
×
147
                    dst: PtrUninit<'dst>,
×
148
                ) -> Result<PtrMut<'dst>, TryIntoInnerError> {
×
149
                    let v = unsafe { src_ptr.read::<NotNan<$float>>() };
×
150
                    Ok(unsafe { dst.put(v.into_inner()) })
×
151
                }
×
152

153
                // Borrow inner float type
154
                unsafe fn try_borrow_inner(
×
155
                    src_ptr: PtrConst<'_>,
×
156
                ) -> Result<PtrConst<'_>, TryBorrowInnerError> {
×
157
                    let v = unsafe { src_ptr.get::<NotNan<$float>>() };
×
158
                    Ok(PtrConst::new(
×
159
                        (&v.into_inner()) as *const $float as *const u8,
×
160
                    ))
×
161
                }
×
162

163
                let mut vtable =
164
                    value_vtable!((), |f, _opts| write!(f, "{}", Self::SHAPE.type_identifier));
×
165
                // Accept parsing as inner T, but enforce NotNan invariant
166
                {
167
                    let vtable = vtable.sized_mut().unwrap();
NEW
168
                    vtable.parse = || {
×
NEW
169
                        Some(|s, target| match s.parse::<$float>() {
×
NEW
170
                            Ok(inner) => match NotNan::new(inner) {
×
NEW
171
                                Ok(not_nan) => Ok(unsafe { target.put(not_nan) }),
×
172
                                Err(_) => {
NEW
173
                                    Err(crate::ParseError::Generic("NaN is not allowed for NotNan"))
×
174
                                }
175
                            },
NEW
176
                            Err(_) => Err(crate::ParseError::Generic(
×
NEW
177
                                "Failed to parse inner type for NotNan",
×
NEW
178
                            )),
×
NEW
179
                        })
×
NEW
180
                    };
×
NEW
181
                    vtable.try_from = || Some(try_from);
×
NEW
182
                    vtable.try_into_inner = || Some(try_into_inner);
×
NEW
183
                    vtable.try_borrow_inner = || Some(try_borrow_inner);
×
184
                }
185
                vtable
186
            };
187

188
            const SHAPE: &'static Shape<'static> = &const {
189
                fn inner_shape() -> &'static Shape<'static> {
×
190
                    <$float as Facet>::SHAPE
×
191
                }
×
192

193
                Shape::builder_for_sized::<Self>()
194
                    .type_identifier("NotNan")
195
                    .ty(Type::User(UserType::Opaque))
196
                    .def(Def::Scalar(
197
                        ScalarDef::builder()
198
                            .affinity(&const { ScalarAffinity::opaque().build() })
199
                            .build(),
200
                    ))
201
                    .inner(inner_shape)
202
                    .build()
203
            };
204
        }
205
    };
206
}
207

208
impl_facet_for_ordered_float_and_notnan!(f32);
209
impl_facet_for_ordered_float_and_notnan!(f64);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc