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:
Wolfgang Bumiller 2023-03-03 14:48:04 +01:00 committed by Thomas Lamprecht
parent 1a46283b78
commit aa10025366
2 changed files with 33 additions and 5 deletions

View File

@ -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),

View File

@ -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)
}
}