'How to handle errors that occur inside an initializer macro?
I have this piece of code:
use std::result::Result;
#[derive(Debug)]
pub struct Addr {
ip: [u8; 4],
port: u16
}
trait IntoAddr {
fn into(self) -> Addr;
}
impl Addr {
pub fn new<T>(args: T) -> Addr
where T: IntoAddr {
args.into()
}
pub fn ip(&self) -> [u8; 4] {
self.ip
}
pub fn port(&self) -> u16 {
self.port
}
}
impl IntoAddr for ([u8; 4], u16) {
fn into(self) -> Addr {
Addr {
self.0,
self.1
}
}
}
impl IntoAddr for ([String; 4], u16) {
fn into(self) -> Addr {
let mut i = -1;
Addr {
arr![self.1[++i].parse().unwrap(); 4],
self.1
}
}
}
I want to either take a ([u8; 4], u16) or ([String; 4], 16) as parameters of new to initialize my struct Addr, what is the correct way to handle the possible parse error inside arr! macro for the string without unwrapping ? Can we put a match statement inside the macro?
Solution 1:[1]
If the initialization may fail, you must return a Result (or allow panic with .unwrap). Use the ? syntax to immediately return an Err if parsing fails.
fn try_from(ip: &[&str; 4], port: u16) -> Result<Addr, ParseIntError> {
Ok(Addr {
ip: [
ip[0].parse()?,
ip[1].parse()?,
ip[2].parse()?,
ip[3].parse()?,
],
port,
})
}
If you really want to use a macro for this, seq-macro seems to do the job.
use seq_macro::seq;
use std::num::ParseIntError;
use std::result::Result;
#[derive(Debug)]
pub struct Addr {
ip: [u8; 4],
port: u16,
}
impl Addr {
fn try_from(ip: &[&str; 4], port: u16) -> Result<Addr, ParseIntError> {
seq!(N in 0..4 {
Ok(Addr {
ip: [ #( ip[N].parse()?, )* ],
port,
})
})
}
}
fn main() {
println!("{:?}", Addr::try_from(&["1", "23", "45", "67"], 80));
println!("{:?}", Addr::try_from(&["1", "23", "45", "foo"], 80));
}
Output:
Ok(Addr { ip: [1, 23, 45, 67], port: 80 })
Err(ParseIntError { kind: InvalidDigit })
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | aedm |
