@@ -138,9 +138,13 @@ use crate::Result;
138
138
/// # Ok(())
139
139
/// }
140
140
/// ```
141
- pub fn regex_from_str ( json : & str , whitespace_pattern : Option < & str > ) -> Result < String > {
141
+ pub fn regex_from_str (
142
+ json : & str ,
143
+ whitespace_pattern : Option < & str > ,
144
+ max_recursion_depth : Option < usize > ,
145
+ ) -> Result < String > {
142
146
let json_value: Value = serde_json:: from_str ( json) ?;
143
- regex_from_value ( & json_value, whitespace_pattern)
147
+ regex_from_value ( & json_value, whitespace_pattern, max_recursion_depth )
144
148
}
145
149
146
150
/// Generates a regular expression string from `serde_json::Value` type of JSON schema.
@@ -178,11 +182,18 @@ pub fn regex_from_str(json: &str, whitespace_pattern: Option<&str>) -> Result<St
178
182
/// # Ok(())
179
183
/// }
180
184
/// ```
181
- pub fn regex_from_value ( json : & Value , whitespace_pattern : Option < & str > ) -> Result < String > {
185
+ pub fn regex_from_value (
186
+ json : & Value ,
187
+ whitespace_pattern : Option < & str > ,
188
+ max_recursion_depth : Option < usize > ,
189
+ ) -> Result < String > {
182
190
let mut parser = parsing:: Parser :: new ( json) ;
183
191
if let Some ( pattern) = whitespace_pattern {
184
192
parser = parser. with_whitespace_pattern ( pattern)
185
193
}
194
+ if let Some ( depth) = max_recursion_depth {
195
+ parser = parser. with_max_recursion_depth ( depth)
196
+ }
186
197
parser. to_regex ( json)
187
198
}
188
199
@@ -1213,7 +1224,7 @@ mod tests {
1213
1224
] ,
1214
1225
) ,
1215
1226
] {
1216
- let result = regex_from_str ( schema, None ) . expect ( "To regex failed" ) ;
1227
+ let result = regex_from_str ( schema, None , None ) . expect ( "To regex failed" ) ;
1217
1228
assert_eq ! ( result, regex, "JSON Schema {} didn't match" , schema) ;
1218
1229
1219
1230
let re = Regex :: new ( & result) . expect ( "Regex failed" ) ;
@@ -1269,7 +1280,7 @@ mod tests {
1269
1280
] ,
1270
1281
) ,
1271
1282
] {
1272
- let regex = regex_from_str ( schema, None ) . expect ( "To regex failed" ) ;
1283
+ let regex = regex_from_str ( schema, None , None ) . expect ( "To regex failed" ) ;
1273
1284
let re = Regex :: new ( & regex) . expect ( "Regex failed" ) ;
1274
1285
for m in a_match {
1275
1286
should_match ( & re, m) ;
@@ -1322,7 +1333,7 @@ mod tests {
1322
1333
vec ! [ r#"{SPACE"date"SPACE:SPACE"2018-11-13"SPACE}"# ] ,
1323
1334
) ,
1324
1335
] {
1325
- let regex = regex_from_str ( schema, whitespace_pattern) . expect ( "To regex failed" ) ;
1336
+ let regex = regex_from_str ( schema, whitespace_pattern, None ) . expect ( "To regex failed" ) ;
1326
1337
assert_eq ! ( regex, expected_regex) ;
1327
1338
1328
1339
let re = Regex :: new ( & regex) . expect ( "Regex failed" ) ;
@@ -1346,7 +1357,7 @@ mod tests {
1346
1357
}
1347
1358
}"## ;
1348
1359
1349
- let regex = regex_from_str ( schema, None ) ;
1360
+ let regex = regex_from_str ( schema, None , None ) ;
1350
1361
assert ! ( regex. is_ok( ) , "{:?}" , regex) ;
1351
1362
1352
1363
// Confirm the depth of 3 recursion levels by default, recursion level starts
@@ -1479,7 +1490,123 @@ mod tests {
1479
1490
"$ref": "#/definitions/typeA"
1480
1491
}"## ;
1481
1492
1482
- let regex = regex_from_str ( schema, None ) ;
1493
+ let regex = regex_from_str ( schema, None , None ) ;
1494
+ assert ! ( regex. is_ok( ) , "{:?}" , regex) ;
1495
+ }
1496
+
1497
+ #[ test]
1498
+ fn quadruple_recursion_doesnt_include_leaf ( ) {
1499
+ let schema = r##"
1500
+ {
1501
+ "definitions": {
1502
+ "typeA": {
1503
+ "type": "object",
1504
+ "properties": {
1505
+ "data": { "type": "string" },
1506
+ "typeB": { "$ref": "#/definitions/typeB" }
1507
+ },
1508
+ "required": ["data", "typeB"]
1509
+ },
1510
+ "typeB": {
1511
+ "type": "object",
1512
+ "properties": {
1513
+ "data": { "type": "string" },
1514
+ "typeC": { "$ref": "#/definitions/typeC" }
1515
+ },
1516
+ "required": ["data", "typeC"]
1517
+ },
1518
+ "typeC": {
1519
+ "type": "object",
1520
+ "properties": {
1521
+ "data": { "type": "string" },
1522
+ "typeD": { "$ref": "#/definitions/typeD" }
1523
+ },
1524
+ "required": ["data", "typeD"]
1525
+ },
1526
+ "typeD": {
1527
+ "type": "object",
1528
+ "properties": {
1529
+ "data": { "type": "string" },
1530
+ "typeE": { "$ref": "#/definitions/typeE" }
1531
+ },
1532
+ "required": ["data", "typeE"]
1533
+ },
1534
+ "typeE": {
1535
+ "type": "object",
1536
+ "properties": {
1537
+ "data": { "type": "string" },
1538
+ "typeA": { "$ref": "#/definitions/typeA" }
1539
+ },
1540
+ "required": ["data", "typeA"]
1541
+ }
1542
+ },
1543
+ "$ref": "#/definitions/typeA"
1544
+ }"## ;
1545
+
1546
+ let regex = regex_from_str ( schema, None , None ) ;
1483
1547
assert ! ( regex. is_ok( ) , "{:?}" , regex) ;
1548
+ let regex_str = regex. unwrap ( ) ;
1549
+ assert ! (
1550
+ !regex_str. contains( "typeE" ) ,
1551
+ "Regex should not contain typeE when max_recursion_depth is not specified"
1552
+ ) ;
1553
+ }
1554
+
1555
+ #[ test]
1556
+ fn quadruple_recursion_includes_leaf_when_max_recursion_depth_is_specified ( ) {
1557
+ let schema = r##"
1558
+ {
1559
+ "definitions": {
1560
+ "typeA": {
1561
+ "type": "object",
1562
+ "properties": {
1563
+ "data": { "type": "string" },
1564
+ "typeB": { "$ref": "#/definitions/typeB" }
1565
+ },
1566
+ "required": ["data", "typeB"]
1567
+ },
1568
+ "typeB": {
1569
+ "type": "object",
1570
+ "properties": {
1571
+ "data": { "type": "string" },
1572
+ "typeC": { "$ref": "#/definitions/typeC" }
1573
+ },
1574
+ "required": ["data", "typeC"]
1575
+ },
1576
+ "typeC": {
1577
+ "type": "object",
1578
+ "properties": {
1579
+ "data": { "type": "string" },
1580
+ "typeD": { "$ref": "#/definitions/typeD" }
1581
+ },
1582
+ "required": ["data", "typeD"]
1583
+ },
1584
+ "typeD": {
1585
+ "type": "object",
1586
+ "properties": {
1587
+ "data": { "type": "string" },
1588
+ "typeE": { "$ref": "#/definitions/typeE" }
1589
+ },
1590
+ "required": ["data", "typeE"]
1591
+ },
1592
+ "typeE": {
1593
+ "type": "object",
1594
+ "properties": {
1595
+ "data": { "type": "string" },
1596
+ "typeA": { "$ref": "#/definitions/typeA" }
1597
+ },
1598
+ "required": ["data", "typeA"]
1599
+ }
1600
+ },
1601
+ "$ref": "#/definitions/typeA"
1602
+ }"## ;
1603
+
1604
+ let regex = regex_from_str ( schema, None , Some ( 4 ) ) ;
1605
+ assert ! ( regex. is_ok( ) , "{:?}" , regex) ;
1606
+ let regex_str = regex. unwrap ( ) ;
1607
+ assert ! (
1608
+ regex_str. contains( "typeE" ) ,
1609
+ "Regex should contain typeE when max_recursion_depth is specified"
1610
+ ) ;
1484
1611
}
1485
1612
}
0 commit comments