@@ -430,15 +430,17 @@ pub fn flatten_config(cfg: &Config) -> Vec<P2PoolConfigEntry> {
430430 e
431431}
432432
433- /// Writes one edited value back into the live `Config`.
434- /// Returns `Err` with a user-facing message on parse failure.
435- /// This is the write-path counterpart to `flatten_config`.
436- pub fn apply_edit ( cfg : & mut Config , index : usize , new_value : & str ) -> Result < ( ) , String > {
437- let entries = flatten_config ( cfg) ;
438- let entry = entries
439- . get ( index)
440- . ok_or_else ( || "index out of range" . to_string ( ) ) ?;
441-
433+ /// Inner dispatch for config edits.
434+ ///
435+ /// Matches a flattened `(section, key)` pair to the corresponding nested field inside `Config` and applies the parsed update.
436+ ///
437+ /// This is split from `apply_edit()` so tests can directly inject
438+ /// synthetic entries and explicitly verify the defensive `_ => unknown field` fallback branch, which `flatten_config()` cannot normally produce.
439+ pub fn dispatch_edit (
440+ cfg : & mut Config ,
441+ entry : & P2PoolConfigEntry ,
442+ new_value : & str ,
443+ ) -> Result < ( ) , String > {
442444 match ( & entry. section , entry. key . as_str ( ) ) {
443445 // Stratum
444446 ( ConfigSection :: Stratum , "hostname" ) => {
@@ -633,6 +635,17 @@ pub fn apply_edit(cfg: &mut Config, index: usize, new_value: &str) -> Result<(),
633635 Ok ( ( ) )
634636}
635637
638+ /// Writes an edited flat-row value back into `Config`.
639+ /// Resolves the selected row from `flatten_config()` and delegates the actual update to `dispatch_edit()`.
640+ /// Returns `Err` if the index is invalid or parsing fails
641+ pub fn apply_edit ( cfg : & mut Config , index : usize , new_value : & str ) -> Result < ( ) , String > {
642+ let entries = flatten_config ( cfg) ;
643+ let entry = entries
644+ . get ( index)
645+ . ok_or_else ( || "index out of range" . to_string ( ) ) ?;
646+ dispatch_edit ( cfg, entry, new_value)
647+ }
648+
636649#[ cfg( test) ]
637650mod tests {
638651 use super :: * ;
@@ -886,13 +899,42 @@ port = 3030
886899
887900 #[ test]
888901 fn apply_edit_unknown_field_hits_fallback_branch ( ) {
889- use super :: apply_edit;
890-
891902 let mut cfg = make_config ( ) ;
892903
893- // Out of bounds → triggers error path
894- let result = apply_edit ( & mut cfg, usize:: MAX , "value" ) ;
904+ // Construct a fake entry with a key that exists in no match arm.
905+ // In normal use flatten_config never produces unknown keys —
906+ // this branch is a defensive guard against future bugs (e.g. a
907+ // new field added to flatten_config but forgotten in dispatch_edit).
908+ let fake_entry = P2PoolConfigEntry {
909+ section : ConfigSection :: Api ,
910+ key : "nonexistent_key_xyz" . to_string ( ) ,
911+ value : String :: new ( ) ,
912+ enabled : true ,
913+ schema : P2PoolFieldSchema {
914+ description : "fake" . to_string ( ) ,
915+ kind : FieldKind :: Required ,
916+ type_hint : "String" . to_string ( ) ,
917+ sensitive : false ,
918+ } ,
919+ } ;
920+ let result = dispatch_edit ( & mut cfg, & fake_entry, "value" ) ;
921+ assert ! ( result. is_err( ) ) ;
922+ assert ! (
923+ result. unwrap_err( ) . contains( "unknown field" ) ,
924+ "error message must mention unknown field"
925+ ) ;
926+ }
895927
928+ #[ test]
929+ fn apply_edit_out_of_bounds_index_returns_error ( ) {
930+ let mut cfg = make_config ( ) ;
931+ // usize::MAX is always out of range — hits the bounds check
932+ // before any section/key dispatch occurs.
933+ let result = apply_edit ( & mut cfg, usize:: MAX , "value" ) ;
896934 assert ! ( result. is_err( ) ) ;
935+ assert ! (
936+ result. unwrap_err( ) . contains( "index out of range" ) ,
937+ "error message must mention index out of range"
938+ ) ;
897939 }
898940}
0 commit comments