Repository: juspay/hyperswitch
File: crates/hyperswitch_connectors/src/connectors/aci/transformers.rs (Rust)

Code before:
    pub entity_id: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for AciAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &ConnectorAuthType) -> Result<Self, Self::Error> {
        if let ConnectorAuthType::BodyKey { api_key, key1 } = item {
            Ok(Self {
                api_key: api_key.to_owned(),
                entity_id: key1.to_owned(),
            })
        } else {
            Err(errors::ConnectorError::FailedToObtainAuthType)?
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum AciRecurringType {
    Initial,
    Repeated,
    RegistrationBased,
}

fn get_str(key: &str, metadata: &serde_json::Value) -> Option<String> {
    metadata
        .get(key)
        .and_then(|v| v.as_str())
        .map(|s| s.to_string())
}

fn determine_recurring_type_for_3ds(
    item: &PaymentsAuthorizeRouterData,
) -> Option<AciRecurringType> {
    if let Some(metadata) = item.connector_meta_data.as_ref() {
        let metadata_value = metadata.peek();
        if let Some(recurring_type) = get_str("recurring_type", metadata_value) {
            return match recurring_type.as_str() {
                "repeated" => Some(AciRecurringType::Repeated),
                "initial" => Some(AciRecurringType::Initial),
                "registration_based" => Some(AciRecurringType::RegistrationBased),
                _ => None,
            };
        }
    }
    None
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]

Review comment (refactor):
this utility fn`get_str`  is not needed separately, you can directly use `get` 
https://docs.rs/std_tools/latest/std_tools/struct.Map.html#method.get

Code after:
    pub entity_id: Secret<String>,
}

impl TryFrom<&ConnectorAuthType> for AciAuthType {
    type Error = error_stack::Report<errors::ConnectorError>;
    fn try_from(item: &ConnectorAuthType) -> Result<Self, Self::Error> {
        if let ConnectorAuthType::BodyKey { api_key, key1 } = item {
            Ok(Self {
                api_key: api_key.to_owned(),
                entity_id: key1.to_owned(),
            })
        } else {
            Err(errors::ConnectorError::FailedToObtainAuthType)?
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum AciRecurringType {
    Initial,
    Repeated,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AciPaymentsRequest {
    #[serde(flatten)]
    pub txn_details: TransactionDetails,
    #[serde(flatten)]
    pub payment_method: PaymentDetails,
    #[serde(flatten)]
    pub instruction: Option<Instruction>,
    pub shopper_result_url: Option<String>,
    #[serde(rename = "customParameters[3DS2_enrolled]")]
    pub three_ds_two_enrolled: Option<bool>,
    pub recurring_type: Option<AciRecurringType>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionDetails {
    pub entity_id: Secret<String>,
    pub amount: StringMajorUnit,
    pub currency: String,
    pub payment_type: AciPaymentType,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AciCancelRequest {