ipv4.rs: Potentially incomplete implementation of Result in `impl TryFrom<Ipv4Addr> for Mask {}`
turgu1 opened this issue · comments
Hello,
I am implementing an instantiation of Wifi using specific IP address, subnet mask and gateway. The following code is close to be complete but I can't retrieve the error result from the try_from call, I can only use the unwrap() call (see line with // <======= comment):
pub struct Wireless {
running: bool,
wifi: Box<EspWifi>,
}
impl Wireless {
pub fn new(cfg: Config) -> Result<Wireless, anyhow::Error> {
let netif_stack = Arc::new(EspNetifStack::new()?);
let sys_loop_stack = Arc::new(EspSysLoopStack::new()?);
let default_nvs = Arc::new(EspDefaultNvs::new()?);
let ssid = cfg.ssid.clone();
let psw = cfg.wifi_password.clone();
let mut wireless = Wireless {
running: false,
wifi: Box::new(EspWifi::new(netif_stack, sys_loop_stack, default_nvs)?),
};
let ap_infos = wireless.wifi.scan()?;
let ours = ap_infos.into_iter().find(|a| a.ssid == ssid);
let channel = if let Some(ours) = ours {
info!(
"Found configured access point {} on channel {}",
ssid, ours.channel
);
Some(ours.channel)
} else {
info!(
"Configured access point {} not found during scanning, will go with unknown channel",
ssid
);
None
};
wireless
.wifi
.set_configuration(&Configuration::Client(ClientConfiguration {
ssid: ssid.clone(),
password: psw.clone(),
ip_conf: Some(
if cfg.ip.is_empty() { ipv4::ClientConfiguration::DHCP(Default::default()) }
else { ipv4::ClientConfiguration::Fixed(ipv4::ClientSettings {
ip: cfg.ip.parse::<Ipv4Addr>()?,
subnet: ipv4::Subnet {
gateway: cfg.gateway.parse::<Ipv4Addr>()?,
mask: ipv4::Mask::try_from(cfg.subnet_mask.parse::<Ipv4Addr>()?).unwrap(), // <==========
},
dns: Some(cfg.dns.parse::<Ipv4Addr>()?),
..Default::default()
}) }
),
..Default::default()
}))?;
I can't replace the .unwrap()
call with ?
as I receive the following message from the analyser:
[Result]()<[Mask](), ()>
Go to Result | Mask
error: the trait bound `(): StdError` is not satisfied
label: the trait `StdError` is not implemented for `()`
note: required because of the requirements on the impl of `From<()>` for `anyhow::Error`
label: the trait `StdError` is not implemented for `()`
note: required because of the requirements on the impl of `FromResidual<Result<Infallible, ()>>` for `Result<Wireless, anyhow::Error>`
label: the trait `StdError` is not implemented for `()`
the trait bound `(): StdError` is not satisfied
required because of the requirements on the impl of `From<()>` for `anyhow::Error`
required because of the requirements on the impl of `FromResidual<Result<Infallible, ()>>` for `Result<Wireless, anyhow::Error>`rustc[E0277](https://doc.rust-lang.org/error-index.html#E0277
Thanks for your help!!
Guy
That's because the implementation of TryFrom
returns an error of type ()
which is not compatible with the STD Error
trait, and as such the conversion of it to anyhow::Error
(via ?
) fails.
Now - I can implement a custom Error type which also implements the STD Error trait (if STD is enabled) and then use it in the TryFrom
trait, but that's a lot of work and might be an overkill for a conversion - which if it fails - cannot return anything meaningful besides "I failed". :)
Regardless, and in the meantime - a quick remedy would be something like:
mask: ipv4::Mask::try_from(cfg.subnet_mask.parse::<Ipv4Addr>()?).map_err(|_| anyhow::anyhow!("Invalid mask"))?
Let me know if that works for you.
UPDATE: Or even
mask: ipv4::Mask::try_from(cfg.subnet_mask.parse::<Ipv4Addr>()?).map_err(|_| anyhow::anyhow!("Invalid mask {}", cfg.subnet_mask))?
Thanks a lot! I've learned something today!! It worked fine!
Cheers!
Guy
Closing for now, if more folks complain, I may implement a better compat with STD.