File tree Expand file tree Collapse file tree 2 files changed +34
-3
lines changed
Expand file tree Collapse file tree 2 files changed +34
-3
lines changed Original file line number Diff line number Diff line change @@ -112,10 +112,16 @@ impl<'a> From<Cow<'a, BStr>> for Path<'a> {
112112
113113 // Check if the value starts with ":(optional)" prefix
114114 if value. starts_with ( OPTIONAL_PREFIX ) {
115- // Strip the prefix and create a path marked as optional
116- let stripped = & value[ OPTIONAL_PREFIX . len ( ) ..] ;
115+ // Strip the prefix while preserving the Cow variant to avoid unnecessary allocations
116+ let stripped = match value {
117+ Cow :: Borrowed ( b) => Cow :: Borrowed ( & b[ OPTIONAL_PREFIX . len ( ) ..] ) ,
118+ Cow :: Owned ( mut b) => {
119+ b. drain ( ..OPTIONAL_PREFIX . len ( ) ) ;
120+ Cow :: Owned ( b)
121+ }
122+ } ;
117123 Path {
118- value : Cow :: Owned ( stripped. into ( ) ) ,
124+ value : stripped,
119125 is_optional : true ,
120126 }
121127 } else {
Original file line number Diff line number Diff line change @@ -131,6 +131,7 @@ mod interpolate {
131131mod optional_prefix {
132132 use std:: borrow:: Cow ;
133133
134+ use bstr:: ByteSlice ;
134135 use crate :: { b, cow_str} ;
135136
136137 #[ test]
@@ -215,4 +216,28 @@ mod optional_prefix {
215216
216217 Ok ( ( ) )
217218 }
219+
220+ #[ test]
221+ fn borrowed_path_stays_borrowed_after_prefix_stripping ( ) {
222+ // Verify that we don't unnecessarily allocate when stripping the prefix from borrowed data
223+ let borrowed_input: & [ u8 ] = b":(optional)/some/path" ;
224+ let path = gix_config_value:: Path :: from ( Cow :: Borrowed ( borrowed_input. as_bstr ( ) ) ) ;
225+
226+ assert ! ( path. is_optional( ) ) ;
227+ assert_eq ! ( path. value. as_ref( ) , b"/some/path" ) ;
228+ // Verify it's still borrowed (no unnecessary allocation)
229+ assert ! ( matches!( path. value, Cow :: Borrowed ( _) ) ) ;
230+ }
231+
232+ #[ test]
233+ fn owned_path_stays_owned_after_prefix_stripping ( ) {
234+ // Verify that owned data remains owned after prefix stripping (but efficiently)
235+ let owned_input = bstr:: BString :: from ( ":(optional)/some/path" ) ;
236+ let path = gix_config_value:: Path :: from ( Cow :: Owned ( owned_input) ) ;
237+
238+ assert ! ( path. is_optional( ) ) ;
239+ assert_eq ! ( path. value. as_ref( ) , b"/some/path" ) ;
240+ // Verify it's still owned
241+ assert ! ( matches!( path. value, Cow :: Owned ( _) ) ) ;
242+ }
218243}
You can’t perform that action at this time.
0 commit comments