You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: startup.rs
    path of file: ./repos/s2n-quic/quic/s2n-quic-core/src/recovery/bbr
    
    the code of the file until where you have to start completion: // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use crate::{
    event::builder::SlowStartExitCause,
    recovery::{
        bbr::{BbrCongestionController, State},
        congestion_controller::Publisher,
    },
};
use num_rational::Ratio;

//= https://tools.ietf.org/id/draft-cardwell-iccrg-bbr-congestion-control-02#2.6
//# A constant specifying the minimum gain value for calculating the pacing rate that will
//# allow the sending rate to double each round (4*ln(2) ~= 2.77)
pub(crate) const PACING_GAIN: Ratio<u64> = Ratio::new_raw(277, 100);

//= https://tools.ietf.org/id/draft-cardwell-iccrg-bbr-congestion-control-02#2.6
//# A constant specifying the minimum gain value for calculating the
//# cwnd that will allow the sending rate to double each round (2.0)
pub(crate) const CWND_GAIN: Ratio<u64> = Ratio::new_raw(2, 1);

/// Methods related to the Startup state
impl BbrCongestionController {
    /// Enter the `Startup` state
    #[inline]
    pub(super) fn enter_startup<Pub: Publisher>(&mut self, publisher: &mut Pub) {
        //= https://tools.ietf.org/id/draft-cardwell-iccrg-bbr-congestion-control-02#4.3.1.1
        //# BBREnterStartup():
        //#   BBR.state = Startup
        //#   BBR.pacing_gain = BBRStartupPacingGain
        //#   BBR.cwnd_gain = BBRStartupCwndGain

        // pacing_gain and cwnd_gain are managed with the State enum

        // New BBR state requires updating the model
     
    
    fn check_startup_done_filled_pipe_on_round_start() {
        let mut bbr = BbrCongestionController::new(MINIMUM_MTU);
        let mut publisher = event::testing::Publisher::snapshot();
        let mut publisher = PathPublisher::new(&mut publisher, path::Id::test_id());
        let now = NoopClock.get_time();

        // Set ECN state to be too high, which would cause the full pipe estimator to be filled
        bbr.ecn_state.on_explicit_congestion(1000);
        bbr.ecn_state
            .on_round_start(1000 * MINIMUM_MTU as u64, MINIMUM_MTU);
        assert!(!bbr.round_counter.round_start());

        // ECN must be too high over 2 rounds to fill the pipe
        bbr.check_startup_done(&mut publisher);
        bbr.check_startup_done(&mut publisher);

        // Still in startup since it wasn't the start of a round when ECN was measured
        assert!(!bbr.full_pipe_estimator.filled_pipe());
        assert!(bbr.state.is_startup());

        bbr.round_counter.set_round_end(100);
        let packet_info = PacketInfo {
            delivered_bytes: 100,
            delivered_time: now,
            lost_bytes: 0,
            ecn_ce_count: 0,
            first_sent_time: now,
            bytes_in_flight: 0,
            is_app_limited: false,
        };
        bbr.round_counter.on_ack(packet_info, 200);
        assert!(bbr.round_counter.round_start());

        // ECN must be too high over 2 rounds to fill the pipe
        bbr.check_startup_done(&mut publisher);
        bbr.check_startup_done(&mut publisher);

        assert!(bbr.full_pipe_estimator.filled_pipe());
        assert!(bbr.state.is_drain());
    }