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

facet-rs / facet / 15200164445

23 May 2025 01:21AM UTC coverage: 57.288% (+0.1%) from 57.185%
15200164445

Pull #666

github

web-flow
Merge 4232978c5 into 4b41e5c8a
Pull Request #666: Add indirection to vtable fns to fix cyclic types

715 of 1482 new or added lines in 34 files covered. (48.25%)

14 existing lines in 5 files now uncovered.

9747 of 17014 relevant lines covered (57.29%)

132.73 hits per line

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

54.22
/facet-core/src/impls_time.rs
1
use alloc::string::String;
2
use time::{OffsetDateTime, UtcDateTime};
3

4
use crate::{
5
    Def, Facet, ParseError, PtrConst, PtrUninit, ScalarAffinity, ScalarDef, Shape, Type, UserType,
6
    ValueVTable, value_vtable,
7
};
8

9
unsafe impl Facet<'_> for UtcDateTime {
10
    const VTABLE: &'static ValueVTable = &const {
11
        let mut vtable = value_vtable!(UtcDateTime, |f, _opts| write!(f, "UtcDateTime"));
×
NEW
12
        vtable.try_from = || {
×
13
            Some(
NEW
14
                |source: PtrConst, source_shape: &Shape, target: PtrUninit| {
×
NEW
15
                    if source_shape.is_type::<String>() {
×
NEW
16
                        let source = unsafe { source.read::<String>() };
×
NEW
17
                        let parsed = UtcDateTime::parse(
×
NEW
18
                            &source,
×
NEW
19
                            &time::format_description::well_known::Rfc3339,
×
20
                        )
NEW
21
                        .map_err(|_| ParseError::Generic("could not parse date"));
×
NEW
22
                        match parsed {
×
NEW
23
                            Ok(val) => Ok(unsafe { target.put(val) }),
×
NEW
24
                            Err(_e) => Err(crate::TryFromError::Generic("could not parse date")),
×
25
                        }
26
                    } else {
NEW
27
                        Err(crate::TryFromError::UnsupportedSourceShape {
×
NEW
28
                            src_shape: source_shape,
×
NEW
29
                            expected: &[String::SHAPE],
×
NEW
30
                        })
×
31
                    }
NEW
32
                },
×
33
            )
NEW
34
        };
×
NEW
35
        vtable.parse = || {
×
NEW
36
            Some(|s: &str, target: PtrUninit| {
×
NEW
37
                let parsed = UtcDateTime::parse(s, &time::format_description::well_known::Rfc3339)
×
NEW
38
                    .map_err(|_| ParseError::Generic("could not parse date"))?;
×
NEW
39
                Ok(unsafe { target.put(parsed) })
×
NEW
40
            })
×
NEW
41
        };
×
NEW
42
        vtable.display = || {
×
43
            Some(|value, f| unsafe {
NEW
44
                let udt = value.get::<UtcDateTime>();
×
NEW
45
                match udt.format(&time::format_description::well_known::Rfc3339) {
×
NEW
46
                    Ok(s) => write!(f, "{s}"),
×
NEW
47
                    Err(_) => write!(f, "<invalid UtcDateTime>"),
×
48
                }
NEW
49
            })
×
NEW
50
        };
×
51
        vtable
52
    };
53

54
    const SHAPE: &'static Shape<'static> = &const {
55
        Shape::builder_for_sized::<Self>()
56
            .ty(Type::User(UserType::Opaque))
57
            .def(Def::Scalar(
58
                ScalarDef::builder()
59
                    .affinity(&const { ScalarAffinity::time().build() })
60
                    .build(),
61
            ))
62
            .build()
63
    };
64
}
65

66
unsafe impl Facet<'_> for OffsetDateTime {
67
    const VTABLE: &'static ValueVTable = &const {
68
        let mut vtable = value_vtable!(OffsetDateTime, |f, _opts| write!(f, "OffsetDateTime"));
4✔
69
        vtable.try_from = || {
1✔
70
            Some(
71
                |source: PtrConst, source_shape: &Shape, target: PtrUninit| {
1✔
72
                    if source_shape.is_type::<String>() {
1✔
73
                        let source = unsafe { source.read::<String>() };
1✔
74
                        let parsed = OffsetDateTime::parse(
1✔
75
                            &source,
1✔
76
                            &time::format_description::well_known::Rfc3339,
1✔
77
                        )
78
                        .map_err(|_| ParseError::Generic("could not parse date"));
1✔
79
                        match parsed {
1✔
80
                            Ok(val) => Ok(unsafe { target.put(val) }),
1✔
NEW
81
                            Err(_e) => Err(crate::TryFromError::Generic("could not parse date")),
×
82
                        }
83
                    } else {
NEW
84
                        Err(crate::TryFromError::UnsupportedSourceShape {
×
NEW
85
                            src_shape: source_shape,
×
NEW
86
                            expected: &[String::SHAPE],
×
NEW
87
                        })
×
88
                    }
89
                },
1✔
90
            )
91
        };
1✔
92
        vtable.parse = || {
1✔
93
            Some(|s: &str, target: PtrUninit| {
1✔
94
                let parsed =
1✔
95
                    OffsetDateTime::parse(s, &time::format_description::well_known::Rfc3339)
1✔
96
                        .map_err(|_| ParseError::Generic("could not parse date"))?;
1✔
97
                Ok(unsafe { target.put(parsed) })
1✔
98
            })
1✔
99
        };
1✔
100
        vtable.display = || {
3✔
101
            Some(|value, f| unsafe {
102
                let odt = value.get::<OffsetDateTime>();
2✔
103
                match odt.format(&time::format_description::well_known::Rfc3339) {
2✔
104
                    Ok(s) => write!(f, "{s}"),
2✔
NEW
105
                    Err(_) => write!(f, "<invalid OffsetDateTime>"),
×
106
                }
107
            })
2✔
108
        };
3✔
109
        vtable
110
    };
111

112
    const SHAPE: &'static Shape<'static> = &const {
113
        Shape::builder_for_sized::<Self>()
114
            .ty(Type::User(UserType::Opaque))
115
            .def(Def::Scalar(
116
                ScalarDef::builder()
117
                    .affinity(&const { ScalarAffinity::time().build() })
118
                    .build(),
119
            ))
120
            .build()
121
    };
122
}
123

124
#[cfg(test)]
125
mod tests {
126
    use core::fmt;
127

128
    use time::OffsetDateTime;
129

130
    use crate::{Facet, PtrConst};
131

132
    #[test]
133
    fn parse_offset_date_time() -> eyre::Result<()> {
1✔
134
        facet_testhelpers::setup();
1✔
135

136
        let target = OffsetDateTime::SHAPE.allocate()?;
1✔
137
        unsafe {
138
            ((OffsetDateTime::VTABLE.parse)().unwrap())("2023-03-14T15:09:26Z", target)?;
1✔
139
        }
140
        let odt: OffsetDateTime = unsafe { target.assume_init().read() };
1✔
141
        assert_eq!(
1✔
142
            odt,
143
            OffsetDateTime::parse(
1✔
144
                "2023-03-14T15:09:26Z",
1✔
145
                &time::format_description::well_known::Rfc3339
1✔
146
            )
147
            .unwrap()
1✔
148
        );
149

150
        struct DisplayWrapper<'a>(PtrConst<'a>);
151

152
        impl fmt::Display for DisplayWrapper<'_> {
153
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1✔
154
                unsafe { ((OffsetDateTime::VTABLE.display)().unwrap())(self.0, f) }
1✔
155
            }
1✔
156
        }
157

158
        let s = format!("{}", DisplayWrapper(PtrConst::new(&odt as *const _)));
1✔
159
        assert_eq!(s, "2023-03-14T15:09:26Z");
1✔
160

161
        // Deallocate the heap allocation to avoid memory leaks under Miri
162
        unsafe {
163
            OffsetDateTime::SHAPE.deallocate_uninit(target)?;
1✔
164
        }
165

166
        Ok(())
1✔
167
    }
1✔
168
}
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

© 2026 Coveralls, Inc