So.... I'm wondering if rather than first_port and last_port this can just take the multiple of NUM_SOURCE_NAT_PORTS. Since NUM_SOURCE_NAT_PORTS is 2^14 and the number of ports is 2^16, there are only 4 possible values. So this could actually take an enum, say, SourceNatPortBlock { Block0, Block1, Block2, Block3 }. That would make this constructor infallible.
Then you can serialize the data in that fashion as well, and deserialization won't require further validation.
Some places may have a port pair, and you can have a constructor that converts that into a SourceNatPortBlock, returning the below error. But places that don't have the raw ports won't have to deal with errors.
Not sure how much it increases work for you, maybe in a followup/after r8 if it disrupts this work too much?
Originally posted by @sunshowers in #5560 (comment)