11//! Validator for `format` keyword.
2- use std:: { net:: IpAddr , str:: FromStr , sync:: Arc } ;
2+ use std:: {
3+ net:: { Ipv4Addr , Ipv6Addr } ,
4+ str:: FromStr ,
5+ sync:: Arc ,
6+ } ;
37
48use fancy_regex:: Regex ;
59use once_cell:: sync:: Lazy ;
@@ -206,13 +210,7 @@ impl Validate for IpV4Validator {
206210 validate ! ( "ipv4" ) ;
207211 fn is_valid ( & self , instance : & Value ) -> bool {
208212 if let Value :: String ( item) = instance {
209- if item. starts_with ( '0' ) {
210- return false ;
211- }
212- match IpAddr :: from_str ( item. as_str ( ) ) {
213- Ok ( i) => i. is_ipv4 ( ) ,
214- Err ( _) => false ,
215- }
213+ Ipv4Addr :: from_str ( item) . is_ok ( )
216214 } else {
217215 true
218216 }
@@ -224,10 +222,7 @@ impl Validate for IpV6Validator {
224222 validate ! ( "ipv6" ) ;
225223 fn is_valid ( & self , instance : & Value ) -> bool {
226224 if let Value :: String ( item) = instance {
227- match IpAddr :: from_str ( item. as_str ( ) ) {
228- Ok ( i) => i. is_ipv6 ( ) ,
229- Err ( _) => false ,
230- }
225+ Ipv6Addr :: from_str ( item) . is_ok ( )
231226 } else {
232227 true
233228 }
@@ -531,6 +526,7 @@ pub(crate) fn compile<'a>(
531526#[ cfg( test) ]
532527mod tests {
533528 use serde_json:: json;
529+ use test_case:: test_case;
534530
535531 use crate :: {
536532 compilation:: JSONSchema , error:: ValidationErrorKind , schemas:: Draft :: Draft201909 ,
@@ -642,4 +638,26 @@ mod tests {
642638 ) ;
643639 assert_eq ! ( "\" custom\" " , validation_error. instance. to_string( ) )
644640 }
641+
642+ #[ test_case( "127.0.0.1" , true ) ]
643+ #[ test_case( "192.168.1.1" , true ) ]
644+ #[ test_case( "10.0.0.1" , true ) ]
645+ #[ test_case( "0.0.0.0" , true ) ]
646+ #[ test_case( "256.1.2.3" , false ; "first octet too large" ) ]
647+ #[ test_case( "1.256.3.4" , false ; "second octet too large" ) ]
648+ #[ test_case( "1.2.256.4" , false ; "third octet too large" ) ]
649+ #[ test_case( "1.2.3.256" , false ; "fourth octet too large" ) ]
650+ #[ test_case( "01.2.3.4" , false ; "leading zero in first octet" ) ]
651+ #[ test_case( "1.02.3.4" , false ; "leading zero in second octet" ) ]
652+ #[ test_case( "1.2.03.4" , false ; "leading zero in third octet" ) ]
653+ #[ test_case( "1.2.3.04" , false ; "leading zero in fourth octet" ) ]
654+ #[ test_case( "1.2.3" , false ; "too few octets" ) ]
655+ #[ test_case( "1.2.3.4.5" , false ; "too many octets" ) ]
656+ fn ip_v4 ( input : & str , expected : bool ) {
657+ let validator = JSONSchema :: options ( )
658+ . should_validate_formats ( true )
659+ . compile ( & json ! ( { "format" : "ipv4" , "type" : "string" } ) )
660+ . expect ( "Invalid schema" ) ;
661+ assert_eq ! ( validator. is_valid( & json!( input) ) , expected) ;
662+ }
645663}
0 commit comments