1515use core:: convert:: TryInto ;
1616use std:: borrow:: Cow ;
1717use std:: cmp:: Ordering ;
18+ use std:: collections:: BTreeMap ;
1819use std:: collections:: VecDeque ;
1920use std:: str:: from_utf8;
2021use std:: str:: from_utf8_unchecked;
@@ -288,7 +289,7 @@ pub fn get_by_name(value: &[u8], name: &str, ignore_case: bool) -> Option<Vec<u8
288289}
289290
290291/// Extracts JSON sub-object at the specified path,
291- /// where path elements can be either field keys or array indexes encoded in utf-8 string .
292+ /// where path elements can be either field keys or array indexes.
292293pub fn get_by_keypath < ' a , I : Iterator < Item = & ' a KeyPath < ' a > > > (
293294 value : & [ u8 ] ,
294295 keypaths : I ,
@@ -2015,6 +2016,211 @@ fn concat_jsonb(left: &[u8], right: &[u8], buf: &mut Vec<u8>) -> Result<(), Erro
20152016 Ok ( ( ) )
20162017}
20172018
2019+ /// Deletes a value from a JSON object by the specified path,
2020+ /// where path elements can be either field keys or array indexes.
2021+ pub fn delete_by_keypath < ' a , I : Iterator < Item = & ' a KeyPath < ' a > > > (
2022+ value : & [ u8 ] ,
2023+ keypath : I ,
2024+ buf : & mut Vec < u8 > ,
2025+ ) -> Result < ( ) , Error > {
2026+ let mut keypath: VecDeque < _ > = keypath. collect ( ) ;
2027+ if !is_jsonb ( value) {
2028+ let mut value = parse_value ( value) ?;
2029+ match value {
2030+ Value :: Array ( ref mut arr) => delete_value_array_by_keypath ( arr, & mut keypath) ,
2031+ Value :: Object ( ref mut obj) => delete_value_object_by_keypath ( obj, & mut keypath) ,
2032+ _ => return Err ( Error :: InvalidJsonType ) ,
2033+ } ;
2034+ value. write_to_vec ( buf) ;
2035+ return Ok ( ( ) ) ;
2036+ }
2037+ delete_by_keypath_jsonb ( value, keypath, buf)
2038+ }
2039+
2040+ fn delete_value_array_by_keypath < ' a > (
2041+ arr : & mut Vec < Value < ' _ > > ,
2042+ keypath : & mut VecDeque < & ' a KeyPath < ' a > > ,
2043+ ) {
2044+ if let Some ( KeyPath :: Index ( idx) ) = keypath. pop_front ( ) {
2045+ let len = arr. len ( ) as i32 ;
2046+ let idx = if * idx < 0 { len - idx. abs ( ) } else { * idx } ;
2047+ if idx < 0 || idx >= len {
2048+ return ;
2049+ }
2050+ if keypath. is_empty ( ) {
2051+ arr. remove ( idx as usize ) ;
2052+ } else {
2053+ match arr[ idx as usize ] {
2054+ Value :: Array ( ref mut arr) => delete_value_array_by_keypath ( arr, keypath) ,
2055+ Value :: Object ( ref mut obj) => delete_value_object_by_keypath ( obj, keypath) ,
2056+ _ => { }
2057+ }
2058+ }
2059+ }
2060+ }
2061+
2062+ fn delete_value_object_by_keypath < ' a > (
2063+ obj : & mut BTreeMap < String , Value < ' _ > > ,
2064+ keypath : & mut VecDeque < & ' a KeyPath < ' a > > ,
2065+ ) {
2066+ if let Some ( path) = keypath. pop_front ( ) {
2067+ match path {
2068+ KeyPath :: QuotedName ( name) | KeyPath :: Name ( name) => {
2069+ if keypath. is_empty ( ) {
2070+ obj. remove ( name. as_ref ( ) ) ;
2071+ } else if let Some ( val) = obj. get_mut ( name. as_ref ( ) ) {
2072+ match val {
2073+ Value :: Array ( ref mut arr) => delete_value_array_by_keypath ( arr, keypath) ,
2074+ Value :: Object ( ref mut obj) => delete_value_object_by_keypath ( obj, keypath) ,
2075+ _ => { }
2076+ }
2077+ }
2078+ }
2079+ _ => { }
2080+ }
2081+ }
2082+ }
2083+
2084+ fn delete_by_keypath_jsonb < ' a > (
2085+ value : & [ u8 ] ,
2086+ mut keypath : VecDeque < & ' a KeyPath < ' a > > ,
2087+ buf : & mut Vec < u8 > ,
2088+ ) -> Result < ( ) , Error > {
2089+ let header = read_u32 ( value, 0 ) ?;
2090+ match header & CONTAINER_HEADER_TYPE_MASK {
2091+ ARRAY_CONTAINER_TAG => {
2092+ match delete_jsonb_array_by_keypath ( value, header, & mut keypath) ? {
2093+ Some ( builder) => {
2094+ builder. build_into ( buf) ;
2095+ }
2096+ None => {
2097+ buf. extend_from_slice ( value) ;
2098+ }
2099+ } ;
2100+ }
2101+ OBJECT_CONTAINER_TAG => {
2102+ match delete_jsonb_object_by_keypath ( value, header, & mut keypath) ? {
2103+ Some ( builder) => {
2104+ builder. build_into ( buf) ;
2105+ }
2106+ None => {
2107+ buf. extend_from_slice ( value) ;
2108+ }
2109+ }
2110+ }
2111+ _ => return Err ( Error :: InvalidJsonType ) ,
2112+ }
2113+ Ok ( ( ) )
2114+ }
2115+
2116+ fn delete_jsonb_array_by_keypath < ' a , ' b > (
2117+ value : & ' b [ u8 ] ,
2118+ header : u32 ,
2119+ keypath : & mut VecDeque < & ' a KeyPath < ' a > > ,
2120+ ) -> Result < Option < ArrayBuilder < ' b > > , Error > {
2121+ let len = ( header & CONTAINER_HEADER_LEN_MASK ) as i32 ;
2122+ match keypath. pop_front ( ) {
2123+ Some ( KeyPath :: Index ( idx) ) => {
2124+ let idx = if * idx < 0 { len - idx. abs ( ) } else { * idx } ;
2125+ if idx < 0 || idx >= len {
2126+ return Ok ( None ) ;
2127+ }
2128+ let mut builder = ArrayBuilder :: new ( len as usize ) ;
2129+ let idx = idx as usize ;
2130+ for ( i, entry) in iterate_array ( value, header) . enumerate ( ) {
2131+ if i != idx {
2132+ builder. push_raw ( entry. 0 , entry. 1 ) ;
2133+ } else if !keypath. is_empty ( ) {
2134+ let item_value = entry. 1 ;
2135+ match entry. 0 . type_code {
2136+ CONTAINER_TAG => {
2137+ let item_header = read_u32 ( item_value, 0 ) ?;
2138+ match item_header & CONTAINER_HEADER_TYPE_MASK {
2139+ ARRAY_CONTAINER_TAG => {
2140+ match delete_jsonb_array_by_keypath (
2141+ item_value,
2142+ item_header,
2143+ keypath,
2144+ ) ? {
2145+ Some ( item_builder) => builder. push_array ( item_builder) ,
2146+ None => return Ok ( None ) ,
2147+ }
2148+ }
2149+ OBJECT_CONTAINER_TAG => {
2150+ match delete_jsonb_object_by_keypath (
2151+ item_value,
2152+ item_header,
2153+ keypath,
2154+ ) ? {
2155+ Some ( item_builder) => builder. push_object ( item_builder) ,
2156+ None => return Ok ( None ) ,
2157+ }
2158+ }
2159+ _ => unreachable ! ( ) ,
2160+ }
2161+ }
2162+ _ => return Ok ( None ) ,
2163+ }
2164+ }
2165+ }
2166+ Ok ( Some ( builder) )
2167+ }
2168+ _ => Ok ( None ) ,
2169+ }
2170+ }
2171+
2172+ fn delete_jsonb_object_by_keypath < ' a , ' b > (
2173+ value : & ' b [ u8 ] ,
2174+ header : u32 ,
2175+ keypath : & mut VecDeque < & ' a KeyPath < ' a > > ,
2176+ ) -> Result < Option < ObjectBuilder < ' b > > , Error > {
2177+ match keypath. pop_front ( ) {
2178+ Some ( path) => match path {
2179+ KeyPath :: QuotedName ( name) | KeyPath :: Name ( name) => {
2180+ let mut builder = ObjectBuilder :: new ( ) ;
2181+ for ( key, jentry, item) in iterate_object_entries ( value, header) {
2182+ if !key. eq ( name) {
2183+ builder. push_raw ( key, jentry, item) ;
2184+ } else if !keypath. is_empty ( ) {
2185+ match jentry. type_code {
2186+ CONTAINER_TAG => {
2187+ let item_header = read_u32 ( item, 0 ) ?;
2188+ match item_header & CONTAINER_HEADER_TYPE_MASK {
2189+ ARRAY_CONTAINER_TAG => match delete_jsonb_array_by_keypath (
2190+ item,
2191+ item_header,
2192+ keypath,
2193+ ) ? {
2194+ Some ( item_builder) => builder. push_array ( key, item_builder) ,
2195+ None => return Ok ( None ) ,
2196+ } ,
2197+ OBJECT_CONTAINER_TAG => {
2198+ match delete_jsonb_object_by_keypath (
2199+ item,
2200+ item_header,
2201+ keypath,
2202+ ) ? {
2203+ Some ( item_builder) => {
2204+ builder. push_object ( key, item_builder)
2205+ }
2206+ None => return Ok ( None ) ,
2207+ }
2208+ }
2209+ _ => unreachable ! ( ) ,
2210+ }
2211+ }
2212+ _ => return Ok ( None ) ,
2213+ }
2214+ }
2215+ }
2216+ Ok ( Some ( builder) )
2217+ }
2218+ _ => Ok ( None ) ,
2219+ } ,
2220+ None => Ok ( None ) ,
2221+ }
2222+ }
2223+
20182224/// Deletes a key (and its value) from a JSON object, or matching string value(s) from a JSON array.
20192225pub fn delete_by_name ( value : & [ u8 ] , name : & str , buf : & mut Vec < u8 > ) -> Result < ( ) , Error > {
20202226 if !is_jsonb ( value) {
@@ -2166,7 +2372,7 @@ fn strip_nulls_array(header: u32, value: &[u8]) -> Result<ArrayBuilder<'_>, Erro
21662372 for ( jentry, item) in iterate_array ( value, header) {
21672373 match jentry. type_code {
21682374 CONTAINER_TAG => {
2169- let item_header = read_u32 ( item, 0 ) . unwrap ( ) ;
2375+ let item_header = read_u32 ( item, 0 ) ? ;
21702376 match item_header & CONTAINER_HEADER_TYPE_MASK {
21712377 OBJECT_CONTAINER_TAG => {
21722378 builder. push_object ( strip_nulls_object ( item_header, item) ?) ;
@@ -2188,7 +2394,7 @@ fn strip_nulls_object(header: u32, value: &[u8]) -> Result<ObjectBuilder<'_>, Er
21882394 for ( key, jentry, item) in iterate_object_entries ( value, header) {
21892395 match jentry. type_code {
21902396 CONTAINER_TAG => {
2191- let item_header = read_u32 ( item, 0 ) . unwrap ( ) ;
2397+ let item_header = read_u32 ( item, 0 ) ? ;
21922398 match item_header & CONTAINER_HEADER_TYPE_MASK {
21932399 OBJECT_CONTAINER_TAG => {
21942400 builder. push_object ( key, strip_nulls_object ( item_header, item) ?) ;
0 commit comments