jsonschema/keywords/
max_properties.rs1#![allow(clippy::float_cmp, clippy::cast_sign_loss)]
2
3use crate::{
4 compiler,
5 error::ValidationError,
6 keywords::{helpers::fail_on_non_positive_integer, CompilationResult},
7 paths::{LazyLocation, Location, RefTracker},
8 validator::{Validate, ValidationContext},
9};
10use serde_json::{Map, Value};
11
12pub(crate) struct MaxPropertiesValidator {
13 limit: u64,
14 location: Location,
15}
16
17impl MaxPropertiesValidator {
18 #[inline]
19 pub(crate) fn compile<'a>(
20 ctx: &compiler::Context,
21 schema: &'a Value,
22 location: Location,
23 ) -> CompilationResult<'a> {
24 if let Some(limit) = schema.as_u64() {
25 return Ok(Box::new(MaxPropertiesValidator { limit, location }));
26 }
27 if ctx.supports_integer_valued_numbers() {
28 if let Some(limit) = schema.as_f64() {
29 if limit.trunc() == limit {
30 #[allow(clippy::cast_possible_truncation)]
31 return Ok(Box::new(MaxPropertiesValidator {
32 limit: limit as u64,
34 location,
35 }));
36 }
37 }
38 }
39 Err(fail_on_non_positive_integer(schema, location))
40 }
41}
42
43impl Validate for MaxPropertiesValidator {
44 fn is_valid(&self, instance: &Value, _ctx: &mut ValidationContext) -> bool {
45 if let Value::Object(item) = instance {
46 if (item.len() as u64) > self.limit {
47 return false;
48 }
49 }
50 true
51 }
52
53 fn validate<'i>(
54 &self,
55 instance: &'i Value,
56 location: &LazyLocation,
57 tracker: Option<&RefTracker>,
58 _ctx: &mut ValidationContext,
59 ) -> Result<(), ValidationError<'i>> {
60 if let Value::Object(item) = instance {
61 if (item.len() as u64) > self.limit {
62 return Err(ValidationError::max_properties(
63 self.location.clone(),
64 crate::paths::capture_evaluation_path(tracker, &self.location),
65 location.into(),
66 instance,
67 self.limit,
68 ));
69 }
70 }
71 Ok(())
72 }
73}
74
75#[inline]
76pub(crate) fn compile<'a>(
77 ctx: &compiler::Context,
78 _: &'a Map<String, Value>,
79 schema: &'a Value,
80) -> Option<CompilationResult<'a>> {
81 let location = ctx.location().join("maxProperties");
82 Some(MaxPropertiesValidator::compile(ctx, schema, location))
83}
84
85#[cfg(test)]
86mod tests {
87 use crate::tests_util;
88 use serde_json::json;
89
90 #[test]
91 fn location() {
92 tests_util::assert_schema_location(
93 &json!({"maxProperties": 1}),
94 &json!({"a": 1, "b": 2}),
95 "/maxProperties",
96 );
97 }
98}