13
13
//! }"#;
14
14
//!
15
15
//! let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
16
- //! let root_obj = root.object_value_or_create().unwrap ();
16
+ //! let root_obj = root.object_value_or_set ();
17
17
//!
18
18
//! root_obj.get("data").unwrap().set_value(json!({
19
19
//! "nested": true
@@ -785,7 +785,7 @@ impl CstContainerNode {
785
785
) ;
786
786
}
787
787
CstInputValue :: Array ( elements) => {
788
- let array_node: CstContainerNode = CstArray :: new ( ) . into ( ) ;
788
+ let array_node: CstContainerNode = CstArray :: new_no_tokens ( ) . into ( ) ;
789
789
self . raw_insert_child ( insert_index, array_node. clone ( ) . into ( ) ) ;
790
790
791
791
array_node. raw_append_child ( CstToken :: new ( '[' ) . into ( ) ) ;
@@ -828,7 +828,7 @@ impl CstContainerNode {
828
828
array_node. raw_append_child ( CstToken :: new ( ']' ) . into ( ) ) ;
829
829
}
830
830
CstInputValue :: Object ( properties) => {
831
- let object_node: CstContainerNode = CstObject :: new ( ) . into ( ) ;
831
+ let object_node: CstContainerNode = CstObject :: new_no_tokens ( ) . into ( ) ;
832
832
self . raw_insert_child ( insert_index, object_node. clone ( ) . into ( ) ) ;
833
833
834
834
object_node. raw_append_child ( CstToken :: new ( '{' ) . into ( ) ) ;
@@ -1020,7 +1020,7 @@ impl CstRootNode {
1020
1020
/// }"#;
1021
1021
///
1022
1022
/// let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
1023
- /// let root_obj = root.object_value_or_create().unwrap ();
1023
+ /// let root_obj = root.object_value_or_set ();
1024
1024
///
1025
1025
/// root_obj.get("data").unwrap().set_value(json!({
1026
1026
/// "nested": true
@@ -1110,7 +1110,7 @@ impl CstRootNode {
1110
1110
let indents = compute_indents ( & self . clone ( ) . into ( ) ) ;
1111
1111
let mut insert_index = if let Some ( root_value) = self . value ( ) {
1112
1112
let index = root_value. child_index ( ) ;
1113
- root_value. remove ( ) ;
1113
+ root_value. remove_raw ( ) ;
1114
1114
index
1115
1115
} else {
1116
1116
let children = self . children ( ) ;
@@ -1145,6 +1145,9 @@ impl CstRootNode {
1145
1145
1146
1146
/// Gets or creates the root value as an object, returns `Some` if successful
1147
1147
/// or `None` if the root value already exists and is not an object.
1148
+ ///
1149
+ /// Note: Use `.object_value_or_set()` to overwrite the root value when
1150
+ /// it's not an object.
1148
1151
pub fn object_value_or_create ( & self ) -> Option < CstObject > {
1149
1152
match self . value ( ) {
1150
1153
Some ( CstNode :: Container ( CstContainerNode :: Object ( node) ) ) => Some ( node) ,
@@ -1156,13 +1159,30 @@ impl CstRootNode {
1156
1159
}
1157
1160
}
1158
1161
1162
+ /// Gets the value if it's an object or sets the root value as an object.
1163
+ ///
1164
+ /// Note: Use `.object_value_or_create()` to not overwrite the root value
1165
+ /// when it's not an object.
1166
+ pub fn object_value_or_set ( & self ) -> CstObject {
1167
+ match self . value ( ) {
1168
+ Some ( CstNode :: Container ( CstContainerNode :: Object ( node) ) ) => node,
1169
+ _ => {
1170
+ self . set_value ( CstInputValue :: Object ( Vec :: new ( ) ) ) ;
1171
+ self . object_value ( ) . unwrap ( )
1172
+ }
1173
+ }
1174
+ }
1175
+
1159
1176
/// Gets the value if its an array.
1160
1177
pub fn array_value ( & self ) -> Option < CstArray > {
1161
1178
self . value ( ) ?. as_array ( )
1162
1179
}
1163
1180
1164
1181
/// Gets or creates the root value as an object, returns `Some` if successful
1165
1182
/// or `None` if the root value already exists and is not an object.
1183
+ ///
1184
+ /// Note: Use `.array_value_or_set()` to overwrite the root value when
1185
+ /// it's not an array.
1166
1186
pub fn array_value_or_create ( & self ) -> Option < CstArray > {
1167
1187
match self . value ( ) {
1168
1188
Some ( CstNode :: Container ( CstContainerNode :: Array ( node) ) ) => Some ( node) ,
@@ -1174,6 +1194,20 @@ impl CstRootNode {
1174
1194
}
1175
1195
}
1176
1196
1197
+ /// Gets the value if it's an object or sets the root value as an object.
1198
+ ///
1199
+ /// Note: Use `.array_value_or_create()` to not overwrite the root value
1200
+ /// when it's not an object.
1201
+ pub fn array_value_or_set ( & self ) -> CstArray {
1202
+ match self . value ( ) {
1203
+ Some ( CstNode :: Container ( CstContainerNode :: Array ( node) ) ) => node,
1204
+ _ => {
1205
+ self . set_value ( CstInputValue :: Array ( Vec :: new ( ) ) ) ;
1206
+ self . array_value ( ) . unwrap ( )
1207
+ }
1208
+ }
1209
+ }
1210
+
1177
1211
/// Ensures this object's values use trailing commas.
1178
1212
///
1179
1213
/// Note: This does not cause future values to use trailing commas.
@@ -1408,10 +1442,17 @@ impl_container_methods!(CstObject, Object);
1408
1442
impl CstObject {
1409
1443
add_root_node_method ! ( ) ;
1410
1444
1411
- fn new ( ) -> Self {
1445
+ fn new_no_tokens ( ) -> Self {
1412
1446
Self ( CstValueInner :: new ( Vec :: new ( ) ) )
1413
1447
}
1414
1448
1449
+ fn new_with_tokens ( ) -> Self {
1450
+ let object = CstObject :: new_no_tokens ( ) ;
1451
+ let container: CstContainerNode = object. clone ( ) . into ( ) ;
1452
+ container. raw_append_children ( vec ! [ CstToken :: new( '{' ) . into( ) , CstToken :: new( '}' ) . into( ) ] ) ;
1453
+ object
1454
+ }
1455
+
1415
1456
/// Array property by name.
1416
1457
///
1417
1458
/// Returns `None` if the property doesn't exist or is not an array.
@@ -1425,6 +1466,9 @@ impl CstObject {
1425
1466
/// Ensures a property exists with an array value returning the array.
1426
1467
///
1427
1468
/// Returns `None` if the property value exists, but is not an array.
1469
+ ///
1470
+ /// Note: Use `.array_value_or_set(..)` to overwrite an existing
1471
+ /// non-array property value.
1428
1472
pub fn array_value_or_create ( & self , name : & str ) -> Option < CstArray > {
1429
1473
match self . get ( name) {
1430
1474
Some ( prop) => match prop. value ( ) ? {
@@ -1438,6 +1482,37 @@ impl CstObject {
1438
1482
}
1439
1483
}
1440
1484
1485
+ /// Ensures a property exists with an array value returning the array.
1486
+ ///
1487
+ /// Note: Use `.array_value_or_create(..)` to not overwrite an existing
1488
+ /// non-array property value.
1489
+ pub fn array_value_or_set ( & self , name : & str ) -> CstArray {
1490
+ match self . get ( name) {
1491
+ Some ( prop) => match prop. value ( ) {
1492
+ Some ( CstNode :: Container ( CstContainerNode :: Array ( node) ) ) => node,
1493
+ Some ( node) => {
1494
+ let mut index = node. child_index ( ) ;
1495
+ node. remove_raw ( ) ;
1496
+ let container: CstContainerNode = prop. clone ( ) . into ( ) ;
1497
+ let array = CstArray :: new_with_tokens ( ) ;
1498
+ container. raw_insert_child ( Some ( & mut index) , array. clone ( ) . into ( ) ) ;
1499
+ array
1500
+ }
1501
+ _ => {
1502
+ let mut index = prop. children ( ) . len ( ) ;
1503
+ let container: CstContainerNode = prop. clone ( ) . into ( ) ;
1504
+ let array = CstArray :: new_with_tokens ( ) ;
1505
+ container. raw_insert_child ( Some ( & mut index) , array. clone ( ) . into ( ) ) ;
1506
+ array
1507
+ }
1508
+ } ,
1509
+ None => {
1510
+ self . append ( name, CstInputValue :: Array ( Vec :: new ( ) ) ) ;
1511
+ self . array_value ( name) . unwrap ( )
1512
+ }
1513
+ }
1514
+ }
1515
+
1441
1516
/// Object property by name.
1442
1517
///
1443
1518
/// Returns `None` if the property doesn't exist or is not an object.
@@ -1451,6 +1526,9 @@ impl CstObject {
1451
1526
/// Ensures a property exists with an object value returning the object.
1452
1527
///
1453
1528
/// Returns `None` if the property value exists, but is not an object.
1529
+ ///
1530
+ /// Note: Use `.object_value_or_set(..)` to overwrite an existing
1531
+ /// non-array property value.
1454
1532
pub fn object_value_or_create ( & self , name : & str ) -> Option < CstObject > {
1455
1533
match self . get ( name) {
1456
1534
Some ( prop) => match prop. value ( ) ? {
@@ -1464,6 +1542,37 @@ impl CstObject {
1464
1542
}
1465
1543
}
1466
1544
1545
+ /// Ensures a property exists with an object value returning the object.
1546
+ ///
1547
+ /// Note: Use `.object_value_or_create(..)` to not overwrite an existing
1548
+ /// non-object property value.
1549
+ pub fn object_value_or_set ( & self , name : & str ) -> CstObject {
1550
+ match self . get ( name) {
1551
+ Some ( prop) => match prop. value ( ) {
1552
+ Some ( CstNode :: Container ( CstContainerNode :: Object ( node) ) ) => node,
1553
+ Some ( node) => {
1554
+ let mut index = node. child_index ( ) ;
1555
+ node. remove_raw ( ) ;
1556
+ let container: CstContainerNode = prop. clone ( ) . into ( ) ;
1557
+ let object = CstObject :: new_with_tokens ( ) ;
1558
+ container. raw_insert_child ( Some ( & mut index) , object. clone ( ) . into ( ) ) ;
1559
+ object
1560
+ }
1561
+ _ => {
1562
+ let mut index = prop. children ( ) . len ( ) ;
1563
+ let container: CstContainerNode = prop. clone ( ) . into ( ) ;
1564
+ let object = CstObject :: new_with_tokens ( ) ;
1565
+ container. raw_insert_child ( Some ( & mut index) , object. clone ( ) . into ( ) ) ;
1566
+ object
1567
+ }
1568
+ } ,
1569
+ None => {
1570
+ self . append ( name, CstInputValue :: Object ( Vec :: new ( ) ) ) ;
1571
+ self . object_value ( name) . unwrap ( )
1572
+ }
1573
+ }
1574
+ }
1575
+
1467
1576
/// Property by name.
1468
1577
///
1469
1578
/// Returns `None` if the property doesn't exist.
@@ -1742,10 +1851,17 @@ impl_container_methods!(CstArray, Array);
1742
1851
impl CstArray {
1743
1852
add_root_node_method ! ( ) ;
1744
1853
1745
- fn new ( ) -> Self {
1854
+ fn new_no_tokens ( ) -> Self {
1746
1855
Self ( CstValueInner :: new ( Vec :: new ( ) ) )
1747
1856
}
1748
1857
1858
+ fn new_with_tokens ( ) -> Self {
1859
+ let array = CstArray :: new_no_tokens ( ) ;
1860
+ let container: CstContainerNode = array. clone ( ) . into ( ) ;
1861
+ container. raw_append_children ( vec ! [ CstToken :: new( '[' ) . into( ) , CstToken :: new( ']' ) . into( ) ] ) ;
1862
+ array
1863
+ }
1864
+
1749
1865
/// Elements of the array.
1750
1866
pub fn elements ( & self ) -> Vec < CstNode > {
1751
1867
self
@@ -2133,7 +2249,7 @@ impl<'a> CstBuilder<'a> {
2133
2249
}
2134
2250
2135
2251
fn build_object ( & mut self , object : ast:: Object < ' _ > ) -> CstContainerNode {
2136
- let container = CstContainerNode :: Object ( CstObject :: new ( ) ) ;
2252
+ let container = CstContainerNode :: Object ( CstObject :: new_no_tokens ( ) ) ;
2137
2253
let mut last_range_end = object. range . start ;
2138
2254
for prop in object. properties {
2139
2255
self . scan_from_to ( & container, last_range_end, prop. range . start ) ;
@@ -2203,7 +2319,7 @@ impl<'a> CstBuilder<'a> {
2203
2319
}
2204
2320
2205
2321
fn build_array ( & mut self , array : ast:: Array < ' _ > ) -> CstContainerNode {
2206
- let container = CstContainerNode :: Array ( CstArray :: new ( ) ) ;
2322
+ let container = CstContainerNode :: Array ( CstArray :: new_no_tokens ( ) ) ;
2207
2323
let mut last_range_end = array. range . start ;
2208
2324
for element in array. elements {
2209
2325
let element_range = element. range ( ) ;
@@ -3460,6 +3576,31 @@ value3: true
3460
3576
) ;
3461
3577
}
3462
3578
3579
+ #[ test]
3580
+ fn or_set_methods ( ) {
3581
+ let cst = build_cst ( "" ) ;
3582
+ let array = cst. array_value_or_set ( ) ;
3583
+ assert_eq ! ( array. to_string( ) , "[]" ) ;
3584
+ assert_eq ! ( cst. to_string( ) , "[]\n " ) ;
3585
+ let object = cst. object_value_or_set ( ) ;
3586
+ assert_eq ! ( object. to_string( ) , "{}" ) ;
3587
+ assert_eq ! ( cst. to_string( ) , "{}\n " ) ;
3588
+ let value = object. array_value_or_set ( "test" ) ;
3589
+ assert_eq ! ( value. to_string( ) , "[]" ) ;
3590
+ assert_eq ! ( cst. to_string( ) , "{\n \" test\" : []\n }\n " ) ;
3591
+ let value = object. object_value_or_set ( "test" ) ;
3592
+ assert_eq ! ( value. to_string( ) , "{}" ) ;
3593
+ assert_eq ! ( cst. to_string( ) , "{\n \" test\" : {}\n }\n " ) ;
3594
+ let value = object. array_value_or_set ( "test" ) ;
3595
+ assert_eq ! ( value. to_string( ) , "[]" ) ;
3596
+ assert_eq ! ( cst. to_string( ) , "{\n \" test\" : []\n }\n " ) ;
3597
+ value. append ( json ! ( 1 ) ) ;
3598
+ assert_eq ! ( cst. to_string( ) , "{\n \" test\" : [1]\n }\n " ) ;
3599
+ let value = object. object_value_or_set ( "test" ) ;
3600
+ assert_eq ! ( value. to_string( ) , "{}" ) ;
3601
+ assert_eq ! ( cst. to_string( ) , "{\n \" test\" : {}\n }\n " ) ;
3602
+ }
3603
+
3463
3604
#[ test]
3464
3605
fn expression_properties_and_values ( ) {
3465
3606
#[ track_caller]
0 commit comments