Skip to content

Commit efe145b

Browse files
committed
Extract common DropGuard struct and NumberExt trait
Both are used in multiple schemars versions so keeping them in utils.rs is a better choice than duplicating them in each file.
1 parent 1c3a1d3 commit efe145b

File tree

4 files changed

+106
-215
lines changed

4 files changed

+106
-215
lines changed

serde_with/src/schemars_0_8.rs

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ use ::schemars_0_8::{
1717
},
1818
JsonSchema,
1919
};
20-
use core::{
21-
mem::ManuallyDrop,
22-
ops::{Deref, DerefMut},
23-
};
2420

2521
//===================================================================
2622
// Trait Definition
@@ -688,9 +684,9 @@ where
688684
};
689685

690686
parents.push(name);
691-
DropGuard::new(parents, |parents| drop(parents.pop()))
687+
utils::DropGuard::new(parents, |parents| drop(parents.pop()))
692688
} else {
693-
DropGuard::unguarded(parents)
689+
utils::DropGuard::unguarded(parents)
694690
};
695691

696692
if let Some(object) = &mut schema.object {
@@ -1290,52 +1286,3 @@ forward_duration_schema!(TimestampSecondsWithFrac);
12901286
forward_duration_schema!(TimestampMilliSecondsWithFrac);
12911287
forward_duration_schema!(TimestampMicroSecondsWithFrac);
12921288
forward_duration_schema!(TimestampNanoSecondsWithFrac);
1293-
1294-
//===================================================================
1295-
// Extra internal helper structs
1296-
1297-
struct DropGuard<T, F: FnOnce(T)> {
1298-
value: ManuallyDrop<T>,
1299-
guard: Option<F>,
1300-
}
1301-
1302-
impl<T, F: FnOnce(T)> DropGuard<T, F> {
1303-
pub fn new(value: T, guard: F) -> Self {
1304-
Self {
1305-
value: ManuallyDrop::new(value),
1306-
guard: Some(guard),
1307-
}
1308-
}
1309-
1310-
pub fn unguarded(value: T) -> Self {
1311-
Self {
1312-
value: ManuallyDrop::new(value),
1313-
guard: None,
1314-
}
1315-
}
1316-
}
1317-
1318-
impl<T, F: FnOnce(T)> Deref for DropGuard<T, F> {
1319-
type Target = T;
1320-
1321-
fn deref(&self) -> &Self::Target {
1322-
&self.value
1323-
}
1324-
}
1325-
1326-
impl<T, F: FnOnce(T)> DerefMut for DropGuard<T, F> {
1327-
fn deref_mut(&mut self) -> &mut Self::Target {
1328-
&mut self.value
1329-
}
1330-
}
1331-
1332-
impl<T, F: FnOnce(T)> Drop for DropGuard<T, F> {
1333-
fn drop(&mut self) {
1334-
// SAFETY: value is known to be initialized since we only ever remove it here.
1335-
let value = unsafe { ManuallyDrop::take(&mut self.value) };
1336-
1337-
if let Some(guard) = self.guard.take() {
1338-
guard(value);
1339-
}
1340-
}
1341-
}

serde_with/src/schemars_0_9.rs

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use crate::{
99
formats::{Flexible, Format, PreferMany, PreferOne, Separator, Strict},
1010
prelude::{Schema as WrapSchema, *},
11+
utils::NumberExt as _,
1112
};
1213
use ::schemars_0_9::{json_schema, JsonSchema, Schema, SchemaGenerator};
1314
use alloc::{
@@ -17,10 +18,6 @@ use alloc::{
1718
rc::Rc,
1819
vec::Vec,
1920
};
20-
use core::{
21-
mem::ManuallyDrop,
22-
ops::{Deref, DerefMut},
23-
};
2421
use serde_json::Value;
2522

2623
//===================================================================
@@ -690,9 +687,9 @@ where
690687
};
691688

692689
parents.push(name);
693-
DropGuard::new(parents, |parents| drop(parents.pop()))
690+
utils::DropGuard::new(parents, |parents| drop(parents.pop()))
694691
} else {
695-
DropGuard::unguarded(parents)
692+
utils::DropGuard::unguarded(parents)
696693
};
697694

698695
// We do comparisons here to avoid lifetime conflicts below
@@ -1286,77 +1283,3 @@ forward_duration_schema!(TimestampSecondsWithFrac);
12861283
forward_duration_schema!(TimestampMilliSecondsWithFrac);
12871284
forward_duration_schema!(TimestampMicroSecondsWithFrac);
12881285
forward_duration_schema!(TimestampNanoSecondsWithFrac);
1289-
1290-
//===================================================================
1291-
// Extra internal helper structs
1292-
1293-
struct DropGuard<T, F: FnOnce(T)> {
1294-
value: ManuallyDrop<T>,
1295-
guard: Option<F>,
1296-
}
1297-
1298-
impl<T, F: FnOnce(T)> DropGuard<T, F> {
1299-
pub fn new(value: T, guard: F) -> Self {
1300-
Self {
1301-
value: ManuallyDrop::new(value),
1302-
guard: Some(guard),
1303-
}
1304-
}
1305-
1306-
pub fn unguarded(value: T) -> Self {
1307-
Self {
1308-
value: ManuallyDrop::new(value),
1309-
guard: None,
1310-
}
1311-
}
1312-
}
1313-
1314-
impl<T, F: FnOnce(T)> Deref for DropGuard<T, F> {
1315-
type Target = T;
1316-
1317-
fn deref(&self) -> &Self::Target {
1318-
&self.value
1319-
}
1320-
}
1321-
1322-
impl<T, F: FnOnce(T)> DerefMut for DropGuard<T, F> {
1323-
fn deref_mut(&mut self) -> &mut Self::Target {
1324-
&mut self.value
1325-
}
1326-
}
1327-
1328-
impl<T, F: FnOnce(T)> Drop for DropGuard<T, F> {
1329-
fn drop(&mut self) {
1330-
// SAFETY: value is known to be initialized since we only ever remove it here.
1331-
let value = unsafe { ManuallyDrop::take(&mut self.value) };
1332-
1333-
if let Some(guard) = self.guard.take() {
1334-
guard(value);
1335-
}
1336-
}
1337-
}
1338-
1339-
trait NumberExt: Sized {
1340-
fn saturating_sub(&self, count: u64) -> Self;
1341-
}
1342-
1343-
impl NumberExt for serde_json::Number {
1344-
fn saturating_sub(&self, count: u64) -> Self {
1345-
if let Some(v) = self.as_u64() {
1346-
return v.saturating_sub(count).into();
1347-
}
1348-
1349-
if let Some(v) = self.as_i64() {
1350-
if count < i64::MAX as u64 {
1351-
return v.saturating_sub(count as _).into();
1352-
}
1353-
}
1354-
1355-
if let Some(v) = self.as_f64() {
1356-
return serde_json::Number::from_f64(v - (count as f64))
1357-
.expect("saturating_sub resulted in NaN");
1358-
}
1359-
1360-
unreachable!()
1361-
}
1362-
}

serde_with/src/schemars_1.rs

Lines changed: 3 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use crate::{
99
formats::{Flexible, Format, PreferMany, PreferOne, Separator, Strict},
1010
prelude::{Schema as WrapSchema, *},
11+
utils::NumberExt as _,
1112
};
1213
use ::schemars_1::{json_schema, JsonSchema, Schema, SchemaGenerator};
1314
use alloc::{
@@ -17,10 +18,6 @@ use alloc::{
1718
rc::Rc,
1819
vec::Vec,
1920
};
20-
use core::{
21-
mem::ManuallyDrop,
22-
ops::{Deref, DerefMut},
23-
};
2421
use serde_json::Value;
2522

2623
//===================================================================
@@ -694,9 +691,9 @@ where
694691
};
695692

696693
parents.push(name);
697-
DropGuard::new(parents, |parents| drop(parents.pop()))
694+
utils::DropGuard::new(parents, |parents| drop(parents.pop()))
698695
} else {
699-
DropGuard::unguarded(parents)
696+
utils::DropGuard::unguarded(parents)
700697
};
701698

702699
// We do comparisons here to avoid lifetime conflicts below
@@ -1293,77 +1290,3 @@ forward_duration_schema!(TimestampSecondsWithFrac);
12931290
forward_duration_schema!(TimestampMilliSecondsWithFrac);
12941291
forward_duration_schema!(TimestampMicroSecondsWithFrac);
12951292
forward_duration_schema!(TimestampNanoSecondsWithFrac);
1296-
1297-
//===================================================================
1298-
// Extra internal helper structs
1299-
1300-
struct DropGuard<T, F: FnOnce(T)> {
1301-
value: ManuallyDrop<T>,
1302-
guard: Option<F>,
1303-
}
1304-
1305-
impl<T, F: FnOnce(T)> DropGuard<T, F> {
1306-
pub fn new(value: T, guard: F) -> Self {
1307-
Self {
1308-
value: ManuallyDrop::new(value),
1309-
guard: Some(guard),
1310-
}
1311-
}
1312-
1313-
pub fn unguarded(value: T) -> Self {
1314-
Self {
1315-
value: ManuallyDrop::new(value),
1316-
guard: None,
1317-
}
1318-
}
1319-
}
1320-
1321-
impl<T, F: FnOnce(T)> Deref for DropGuard<T, F> {
1322-
type Target = T;
1323-
1324-
fn deref(&self) -> &Self::Target {
1325-
&self.value
1326-
}
1327-
}
1328-
1329-
impl<T, F: FnOnce(T)> DerefMut for DropGuard<T, F> {
1330-
fn deref_mut(&mut self) -> &mut Self::Target {
1331-
&mut self.value
1332-
}
1333-
}
1334-
1335-
impl<T, F: FnOnce(T)> Drop for DropGuard<T, F> {
1336-
fn drop(&mut self) {
1337-
// SAFETY: value is known to be initialized since we only ever remove it here.
1338-
let value = unsafe { ManuallyDrop::take(&mut self.value) };
1339-
1340-
if let Some(guard) = self.guard.take() {
1341-
guard(value);
1342-
}
1343-
}
1344-
}
1345-
1346-
trait NumberExt: Sized {
1347-
fn saturating_sub(&self, count: u64) -> Self;
1348-
}
1349-
1350-
impl NumberExt for serde_json::Number {
1351-
fn saturating_sub(&self, count: u64) -> Self {
1352-
if let Some(v) = self.as_u64() {
1353-
return v.saturating_sub(count).into();
1354-
}
1355-
1356-
if let Some(v) = self.as_i64() {
1357-
if count < i64::MAX as u64 {
1358-
return v.saturating_sub(count as _).into();
1359-
}
1360-
}
1361-
1362-
if let Some(v) = self.as_f64() {
1363-
return serde_json::Number::from_f64(v - (count as f64))
1364-
.expect("saturating_sub resulted in NaN");
1365-
}
1366-
1367-
unreachable!()
1368-
}
1369-
}

serde_with/src/utils.rs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,101 @@ pub(crate) fn get_unexpected_u128(value: u128, buf: &mut [u8; 58]) -> Unexpected
240240
fmt::Write::write_fmt(&mut writer, format_args!("integer `{value}` as u128")).unwrap();
241241
Unexpected::Other(writer.into_str())
242242
}
243+
244+
#[cfg(any(
245+
feature = "schemars_0_8",
246+
feature = "schemars_0_9",
247+
feature = "schemars_1"
248+
))]
249+
pub(crate) struct DropGuard<T, F: FnOnce(T)> {
250+
value: core::mem::ManuallyDrop<T>,
251+
guard: Option<F>,
252+
}
253+
254+
#[cfg(any(
255+
feature = "schemars_0_8",
256+
feature = "schemars_0_9",
257+
feature = "schemars_1"
258+
))]
259+
impl<T, F: FnOnce(T)> DropGuard<T, F> {
260+
pub fn new(value: T, guard: F) -> Self {
261+
Self {
262+
value: core::mem::ManuallyDrop::new(value),
263+
guard: Some(guard),
264+
}
265+
}
266+
267+
pub fn unguarded(value: T) -> Self {
268+
Self {
269+
value: core::mem::ManuallyDrop::new(value),
270+
guard: None,
271+
}
272+
}
273+
}
274+
275+
#[cfg(any(
276+
feature = "schemars_0_8",
277+
feature = "schemars_0_9",
278+
feature = "schemars_1"
279+
))]
280+
impl<T, F: FnOnce(T)> core::ops::Deref for DropGuard<T, F> {
281+
type Target = T;
282+
283+
fn deref(&self) -> &Self::Target {
284+
&self.value
285+
}
286+
}
287+
288+
#[cfg(any(
289+
feature = "schemars_0_8",
290+
feature = "schemars_0_9",
291+
feature = "schemars_1"
292+
))]
293+
impl<T, F: FnOnce(T)> core::ops::DerefMut for DropGuard<T, F> {
294+
fn deref_mut(&mut self) -> &mut Self::Target {
295+
&mut self.value
296+
}
297+
}
298+
299+
#[cfg(any(
300+
feature = "schemars_0_8",
301+
feature = "schemars_0_9",
302+
feature = "schemars_1"
303+
))]
304+
impl<T, F: FnOnce(T)> Drop for DropGuard<T, F> {
305+
fn drop(&mut self) {
306+
// SAFETY: value is known to be initialized since we only ever remove it here.
307+
let value = unsafe { core::mem::ManuallyDrop::take(&mut self.value) };
308+
309+
if let Some(guard) = self.guard.take() {
310+
guard(value);
311+
}
312+
}
313+
}
314+
315+
#[cfg(any(feature = "schemars_0_9", feature = "schemars_1"))]
316+
pub(crate) trait NumberExt: Sized {
317+
fn saturating_sub(&self, count: u64) -> Self;
318+
}
319+
320+
#[cfg(any(feature = "schemars_0_9", feature = "schemars_1"))]
321+
impl NumberExt for serde_json::Number {
322+
fn saturating_sub(&self, count: u64) -> Self {
323+
if let Some(v) = self.as_u64() {
324+
return v.saturating_sub(count).into();
325+
}
326+
327+
if let Some(v) = self.as_i64() {
328+
if count < i64::MAX as u64 {
329+
return v.saturating_sub(count as _).into();
330+
}
331+
}
332+
333+
if let Some(v) = self.as_f64() {
334+
return serde_json::Number::from_f64(v - (count as f64))
335+
.expect("saturating_sub resulted in NaN");
336+
}
337+
338+
unreachable!()
339+
}
340+
}

0 commit comments

Comments
 (0)