diff --git a/crates/lox-library/src/lib.rs b/crates/lox-library/src/lib.rs index 7ac891e..860c98b 100644 --- a/crates/lox-library/src/lib.rs +++ b/crates/lox-library/src/lib.rs @@ -519,111 +519,109 @@ impl BridgeAuth { ) -> ReplaceSuccess { let mut res = ReplaceSuccess::NotFound; let reachable_bridges = &self.bridge_table.reachable.clone(); - match reachable_bridges.get(bridge) { - Some(positions) => { - if let Some(replacement) = available_bridge { - for (bucketnum, offset) in positions.iter() { - let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { - Some(bridgelines) => *bridgelines, - None => return ReplaceSuccess::NotFound, - }; - assert!(bridgelines[*offset] == *bridge); - bridgelines[*offset] = *replacement; - self.bridge_table.buckets.insert(*bucketnum, bridgelines); - // Remove the bridge from the reachable bridges and add new bridge - self.bridge_table - .reachable - .insert(*replacement, positions.clone()); - // Remove the bridge from the bucket - self.bridge_table.reachable.remove(bridge); - } - res = ReplaceSuccess::Replaced - } else if !self.bridge_table.unallocated_bridges.is_empty() { - let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap(); - for (bucketnum, offset) in positions.iter() { - let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { - Some(bridgelines) => *bridgelines, - // This should not happen if the rest of the function is correct, we can assume unwrap will succeed - None => return ReplaceSuccess::NotReplaced, - }; - assert!(bridgelines[*offset] == *bridge); - bridgelines[*offset] = *replacement; - self.bridge_table.buckets.insert(*bucketnum, bridgelines); - self.bridge_table - .reachable - .insert(*replacement, positions.clone()); - // Remove the bridge from the bucket - self.bridge_table.reachable.remove(bridge); - } - res = ReplaceSuccess::Replaced - } else if !self.bridge_table.spares.is_empty() { - // First get the bucketnums for the replacement bridge in case it is a spare - let mut bucketnums: Vec = Vec::new(); - for (bucketnum, _) in positions.iter() { - bucketnums.push(*bucketnum); - } - // Get the first spare and remove it from the spares set. - let mut spare = *self.bridge_table.spares.iter().next().unwrap(); - // Check that the first spare in the list of spares is not the one to be replaced - if bucketnums.contains(&spare) { - // If it is, take the last spare instead - spare = *self.bridge_table.spares.iter().last().unwrap(); - // If this is the same bucketnum, there is only one spare bucket with the bridge - // to be replaced in it, so don't replace it. - if bucketnums.contains(&spare) { - res = ReplaceSuccess::NotReplaced; - return res; - } - } - self.bridge_table.spares.remove(&spare); - self.bridge_table.recycleable_keys.push(spare); - // Get the actual bridges from the spare bucket - let spare_bucket = match self.bridge_table.buckets.remove(&spare) { - Some(spare_bucket) => spare_bucket, - // This should not happen if the rest of the functions are correct, we can assume unwrap will succeed - None => return ReplaceSuccess::NotReplaced, - }; - // Remove the spare bucket uid from the keys map - self.bridge_table.keys.remove(&spare); - let mut replacement: &BridgeLine = &BridgeLine::default(); - // Make the first spare the replacement bridge, add the others to the set of - // unallocated_bridges - for spare_bridge in spare_bucket.iter() { - if replacement.port > 0 { - self.bridge_table.unallocated_bridges.push(*spare_bridge); - // Mark bucket as unreachable while it is unallocated - self.bridge_table.reachable.remove(spare_bridge); - } else { - replacement = spare_bridge; - } - } - for (bucketnum, offset) in positions.iter() { - let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { - Some(bridgelines) => *bridgelines, - None => return ReplaceSuccess::NotReplaced, - }; - assert!(bridgelines[*offset] == *bridge); - bridgelines[*offset] = *replacement; - self.bridge_table.buckets.insert(*bucketnum, bridgelines); - self.bridge_table - .reachable - .insert(*replacement, positions.clone()); - // Remove the bridge from the bucket - self.bridge_table.reachable.remove(bridge); - } - res = ReplaceSuccess::Replaced - } else { - println!("No available bridges"); - // If there are no available bridges that can be assigned here, the only thing - // that can be done is return an indication that updating the gone bridge - // didn't work. - // In this case, we do not mark the bridge as unreachable or remove it from the - // reachable bridges so that we can still find it when a new bridge does become available - res = ReplaceSuccess::NotReplaced + let Some(positions) = reachable_bridges.get(bridge) else { + return res; + }; + if let Some(replacement) = available_bridge { + for (bucketnum, offset) in positions.iter() { + let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { + Some(bridgelines) => *bridgelines, + None => return ReplaceSuccess::NotFound, + }; + assert!(bridgelines[*offset] == *bridge); + bridgelines[*offset] = *replacement; + self.bridge_table.buckets.insert(*bucketnum, bridgelines); + // Remove the bridge from the reachable bridges and add new bridge + self.bridge_table + .reachable + .insert(*replacement, positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); + } + res = ReplaceSuccess::Replaced + } else if !self.bridge_table.unallocated_bridges.is_empty() { + let replacement = &self.bridge_table.unallocated_bridges.pop().unwrap(); + for (bucketnum, offset) in positions.iter() { + let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { + Some(bridgelines) => *bridgelines, + // This should not happen if the rest of the function is correct, we can assume unwrap will succeed + None => return ReplaceSuccess::NotReplaced, + }; + assert!(bridgelines[*offset] == *bridge); + bridgelines[*offset] = *replacement; + self.bridge_table.buckets.insert(*bucketnum, bridgelines); + self.bridge_table + .reachable + .insert(*replacement, positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); + } + res = ReplaceSuccess::Replaced + } else if !self.bridge_table.spares.is_empty() { + // First get the bucketnums for the replacement bridge in case it is a spare + let mut bucketnums: Vec = Vec::new(); + for (bucketnum, _) in positions.iter() { + bucketnums.push(*bucketnum); + } + // Get the first spare and remove it from the spares set. + let mut spare = *self.bridge_table.spares.iter().next().unwrap(); + // Check that the first spare in the list of spares is not the one to be replaced + if bucketnums.contains(&spare) { + // If it is, take the last spare instead + spare = *self.bridge_table.spares.iter().last().unwrap(); + // If this is the same bucketnum, there is only one spare bucket with the bridge + // to be replaced in it, so don't replace it. + if bucketnums.contains(&spare) { + res = ReplaceSuccess::NotReplaced; + return res; } } - None => return res, - }; + self.bridge_table.spares.remove(&spare); + self.bridge_table.recycleable_keys.push(spare); + // Get the actual bridges from the spare bucket + let spare_bucket = match self.bridge_table.buckets.remove(&spare) { + Some(spare_bucket) => spare_bucket, + // This should not happen if the rest of the functions are correct, we can assume unwrap will succeed + None => return ReplaceSuccess::NotReplaced, + }; + // Remove the spare bucket uid from the keys map + self.bridge_table.keys.remove(&spare); + let mut replacement: &BridgeLine = &BridgeLine::default(); + // Make the first spare the replacement bridge, add the others to the set of + // unallocated_bridges + for spare_bridge in spare_bucket.iter() { + if replacement.port > 0 { + self.bridge_table.unallocated_bridges.push(*spare_bridge); + // Mark bucket as unreachable while it is unallocated + self.bridge_table.reachable.remove(spare_bridge); + } else { + replacement = spare_bridge; + } + } + for (bucketnum, offset) in positions.iter() { + let mut bridgelines = match self.bridge_table.buckets.get(bucketnum) { + Some(bridgelines) => *bridgelines, + None => return ReplaceSuccess::NotReplaced, + }; + assert!(bridgelines[*offset] == *bridge); + bridgelines[*offset] = *replacement; + self.bridge_table.buckets.insert(*bucketnum, bridgelines); + self.bridge_table + .reachable + .insert(*replacement, positions.clone()); + // Remove the bridge from the bucket + self.bridge_table.reachable.remove(bridge); + } + res = ReplaceSuccess::Replaced + } else { + println!("No available bridges"); + // If there are no available bridges that can be assigned here, the only thing + // that can be done is return an indication that updating the gone bridge + // didn't work. + // In this case, we do not mark the bridge as unreachable or remove it from the + // reachable bridges so that we can still find it when a new bridge does become available + res = ReplaceSuccess::NotReplaced + } res }