forked from Proxmox/proxmox
schema: guard property string constraint checking
StringSchema::check_constraint runs `parse_property_string` for property strings, but when we deserialize a `PropertyString` we immediately follow that up with deserializing it using the schema, so there's no need to check it beforehand. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
1a46283b78
commit
aa10025366
@ -1,6 +1,7 @@
|
||||
//! Property string deserialization.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::cell::Cell;
|
||||
use std::fmt;
|
||||
use std::ops::Range;
|
||||
|
||||
@ -18,6 +19,25 @@ pub use extract::ExtractValueDeserializer;
|
||||
|
||||
use cow3::{str_slice_to_range, Cow3};
|
||||
|
||||
// Used to disable calling `check_constraints` on a `StringSchema` if it is being deserialized
|
||||
// for a `PropertyString`, which performs its own checking.
|
||||
thread_local! {
|
||||
static IN_PROPERTY_STRING: Cell<bool> = Cell::new(false);
|
||||
}
|
||||
|
||||
pub(crate) struct InPropertyStringGuard;
|
||||
|
||||
pub(crate) fn set_in_property_string() -> InPropertyStringGuard {
|
||||
IN_PROPERTY_STRING.with(|v| v.set(true));
|
||||
InPropertyStringGuard
|
||||
}
|
||||
|
||||
impl Drop for InPropertyStringGuard {
|
||||
fn drop(&mut self) {
|
||||
IN_PROPERTY_STRING.with(|v| v.set(false));
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Error(Cow<'static, str>);
|
||||
|
||||
@ -86,9 +106,11 @@ impl<'de, 'i> SchemaDeserializer<'de, 'i> {
|
||||
where
|
||||
V: de::Visitor<'de>,
|
||||
{
|
||||
schema
|
||||
.check_constraints(&self.input)
|
||||
.map_err(|err| Error::invalid(err))?;
|
||||
if !IN_PROPERTY_STRING.with(|v| v.get()) {
|
||||
schema
|
||||
.check_constraints(&self.input)
|
||||
.map_err(|err| Error::invalid(err))?;
|
||||
}
|
||||
match self.input {
|
||||
Cow3::Original(input) => visitor.visit_borrowed_str(input),
|
||||
Cow3::Intermediate(input) => visitor.visit_str(input),
|
||||
|
@ -267,9 +267,11 @@ where
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
use crate::de::{set_in_property_string, InPropertyStringGuard};
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
struct V<T>(PhantomData<T>);
|
||||
struct V<T>(InPropertyStringGuard, PhantomData<T>);
|
||||
|
||||
impl<'de, T> serde::de::Visitor<'de> for V<T>
|
||||
where
|
||||
@ -292,6 +294,7 @@ where
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
drop(self); // unset IN_PROPERTY_STRING
|
||||
T::deserialize(crate::de::SchemaDeserializer::new(s, &T::API_SCHEMA))
|
||||
.map_err(|err| E::custom(err.to_string()))
|
||||
}
|
||||
@ -300,12 +303,15 @@ where
|
||||
where
|
||||
E: serde::de::Error,
|
||||
{
|
||||
drop(self); // unset IN_PROPERTY_STRING
|
||||
T::deserialize(crate::de::SchemaDeserializer::new(s, &T::API_SCHEMA))
|
||||
.map_err(|err| E::custom(err.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_string(V(PhantomData)).map(Self)
|
||||
deserializer
|
||||
.deserialize_string(V(set_in_property_string(), PhantomData))
|
||||
.map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user