33use std:: borrow:: Cow ;
44
55use line_index:: { LineCol , TextRange , TextSize } ;
6- use serde:: Serialize ;
7-
8- /// Represents a route component in a YAML path.
9- #[ derive( Serialize , Clone , Debug ) ]
10- pub enum RouteComponent < ' doc > {
11- /// A key in a mapping.
12- Key ( & ' doc str ) ,
13- /// An index in a sequence.
14- Index ( usize ) ,
15- }
16-
17- impl From < usize > for RouteComponent < ' _ > {
18- fn from ( value : usize ) -> Self {
19- Self :: Index ( value)
20- }
21- }
22-
23- impl < ' doc > From < & ' doc str > for RouteComponent < ' doc > {
24- fn from ( value : & ' doc str ) -> Self {
25- Self :: Key ( value)
26- }
27- }
28-
29- /// Represents a route (path) to a YAML feature.
30- #[ derive( Serialize , Clone , Debug ) ]
31- pub struct Route < ' doc > {
32- components : Vec < RouteComponent < ' doc > > ,
33- }
34-
35- impl Default for Route < ' _ > {
36- fn default ( ) -> Self {
37- Self :: new ( )
38- }
39- }
40-
41- impl < ' doc > Route < ' doc > {
42- /// Create a new empty route.
43- pub fn new ( ) -> Route < ' doc > {
44- Self {
45- components : Default :: default ( ) ,
46- }
47- }
48-
49- /// Create a new route with the given keys appended.
50- pub fn with_keys ( & self , keys : & [ RouteComponent < ' doc > ] ) -> Route < ' doc > {
51- let mut components = self . components . clone ( ) ;
52- components. extend ( keys. iter ( ) . cloned ( ) ) ;
53- Route { components }
54- }
55-
56- /// Check if this route is the root route (empty).
57- pub fn is_root ( & self ) -> bool {
58- self . components . is_empty ( )
59- }
60-
61- /// Convert this route to a yamlpath query.
62- pub fn to_query ( & self ) -> Option < yamlpath:: Query < ' doc > > {
63- if self . is_root ( ) {
64- return None ;
65- }
66-
67- let mut builder = yamlpath:: QueryBuilder :: new ( ) ;
68-
69- for component in & self . components {
70- builder = match component {
71- RouteComponent :: Key ( key) => builder. key ( key) ,
72- RouteComponent :: Index ( idx) => builder. index ( * idx) ,
73- }
74- }
75-
76- Some ( builder. build ( ) )
77- }
78- }
79-
80- impl < ' doc > From < Vec < RouteComponent < ' doc > > > for Route < ' doc > {
81- fn from ( components : Vec < RouteComponent < ' doc > > ) -> Self {
82- Self { components }
83- }
84- }
85-
86- /// Macro to create a route from a series of keys and indices.
87- #[ macro_export]
88- macro_rules! route {
89- ( $( $key: expr) ,* $( , ) ?) => {
90- $crate:: Route :: from(
91- vec![ $( $crate:: RouteComponent :: from( $key) ) ,* ]
92- )
93- } ;
94- ( ) => {
95- $crate:: Route :: new( )
96- } ;
97- }
986
997/// Error types for YAML patch operations
1008#[ derive( thiserror:: Error , Debug ) ]
@@ -189,7 +97,7 @@ impl Style {
18997#[ derive( Debug , Clone ) ]
19098pub struct Patch < ' doc > {
19199 /// The route to the feature to patch.
192- pub route : Route < ' doc > ,
100+ pub route : yamlpath :: Route < ' doc > ,
193101 /// The operation to perform on the feature.
194102 pub operation : Op < ' doc > ,
195103}
@@ -375,11 +283,7 @@ fn apply_single_patch(
375283 // Check to see whether `key` is already present within the route.
376284 // NOTE: Safe unwrap, since `with_keys` ensures we always have at
377285 // least one component.
378- let key_query = patch
379- . route
380- . with_keys ( & [ key. as_str ( ) . into ( ) ] )
381- . to_query ( )
382- . unwrap ( ) ;
286+ let key_query = patch. route . with_key ( key. as_str ( ) ) ;
383287
384288 if document. query_exists ( & key_query) {
385289 return Err ( Error :: InvalidOperation ( format ! (
@@ -389,7 +293,7 @@ fn apply_single_patch(
389293 ) ) ) ;
390294 }
391295
392- let feature = if patch. route . is_root ( ) {
296+ let feature = if patch. route . is_empty ( ) {
393297 document. top_feature ( ) ?
394298 } else {
395299 route_to_feature_exact ( & patch. route , document) ?. ok_or_else ( || {
@@ -428,7 +332,7 @@ fn apply_single_patch(
428332 yamlpath:: Document :: new ( result) . map_err ( Error :: from)
429333 }
430334 Op :: MergeInto { key, updates } => {
431- let existing_key_route = patch. route . with_keys ( & [ key. as_str ( ) . into ( ) ] ) ;
335+ let existing_key_route = patch. route . with_key ( key. as_str ( ) ) ;
432336 match route_to_feature_exact ( & existing_key_route, document) {
433337 // The key already exists, and has a nonempty body.
434338 Ok ( Some ( existing_feature) ) => {
@@ -474,7 +378,7 @@ fn apply_single_patch(
474378 current_document = apply_single_patch (
475379 & current_document,
476380 & Patch {
477- route : existing_key_route. with_keys ( & [ k. as_str ( ) . into ( ) ] ) ,
381+ route : existing_key_route. with_key ( k. as_str ( ) ) ,
478382 operation : Op :: Replace ( v. clone ( ) ) ,
479383 } ,
480384 ) ?;
@@ -514,7 +418,7 @@ fn apply_single_patch(
514418 }
515419 }
516420 Op :: Remove => {
517- if patch. route . is_root ( ) {
421+ if patch. route . is_empty ( ) {
518422 return Err ( Error :: InvalidOperation (
519423 "Cannot remove root document" . to_string ( ) ,
520424 ) ) ;
@@ -542,23 +446,17 @@ fn apply_single_patch(
542446}
543447
544448pub fn route_to_feature_pretty < ' a > (
545- route : & Route < ' _ > ,
449+ route : & yamlpath :: Route < ' _ > ,
546450 doc : & ' a yamlpath:: Document ,
547451) -> Result < yamlpath:: Feature < ' a > , Error > {
548- match route. to_query ( ) {
549- Some ( query) => doc. query_pretty ( & query) . map_err ( Error :: from) ,
550- None => Ok ( doc. root ( ) ) ,
551- }
452+ doc. query_pretty ( route) . map_err ( Error :: from)
552453}
553454
554455pub fn route_to_feature_exact < ' a > (
555- route : & Route < ' _ > ,
456+ route : & yamlpath :: Route < ' _ > ,
556457 doc : & ' a yamlpath:: Document ,
557458) -> Result < Option < yamlpath:: Feature < ' a > > , Error > {
558- match route. to_query ( ) {
559- Some ( query) => doc. query_exact ( & query) . map_err ( Error :: from) ,
560- None => Ok ( Some ( doc. root ( ) ) ) ,
561- }
459+ doc. query_exact ( route) . map_err ( Error :: from)
562460}
563461
564462/// Serialize a serde_yaml::Value to a YAML string, handling different types appropriately
0 commit comments