Estou trabalhando em uma função que converte um valor JSON em um i32
, retornando um erro se qualquer etapa da conversão falhar.
fn json_to_block_height(height: Value) -> Result<i32, RPCError> {
let err_msg = "Invalid height".to_string();
let height = match height {
Value::Number(h) => Ok(h),
_ => Err(RPCError::CustomError(1, err_msg.clone())),
}?;
let height = height
.as_i64()
.ok_or(RPCError::CustomError(1, err_msg.clone()))?;
if height < 0 {
return Err(RPCError::CustomError(1, err_msg));
}
i32::try_from(height).map_err(|_| RPCError::CustomError(1, err_msg))
}
Existe alguma boa maneira de evitar a clonagem desnecessária da mensagem de erro no match
branch e no ok_or
argumento, além de desenrolar o código inteiro com if...else...
branches explícitos? Tecnicamente, se qualquer uma dessas condições de erro for atendida, o código a seguir será inacessível, então nunca precisaremos realmente mover essa String em um mundo perfeito.
Tentei substituir o ok_or(RPCError::CustomError(1, err_msg.clone())
método por ok_or_else(|| RPCError::CustomError(1, err_msg.clone())
, mas o err_msg ainda parece ser capturado e movido no fechamento.
Pergunta bônus: haveria alguma melhoria de desempenho ao tornar o código mais detalhado com ramificações explícitas para evitar cópias desnecessárias, ou a solução "idiomatic rust" tem mais desempenho apesar dessas cópias?