Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP attempt to implement more general range support #4034

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

tmccombs
Copy link
Contributor

@tmccombs tmccombs commented Aug 7, 2022

This is still very much a work in progress, but I'd like to put it up to see if this is a direction worth pursuing.

See #3895

src/builder/value_parser.rs Outdated Show resolved Hide resolved
/// let port: u16 = *m.get_one("port").expect("required");
/// assert_eq!(port, 3001);
/// ```
fn in_range<R: RangeBounds<Self::Value>>(self, range: R) -> InRange<Self>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure how I feel about this being on the trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't love it either. Some other options would be a standalone function or macro (ex range_parser!(u16: 3000..4000)). Or maybe creating a different trait for types that can be restricted to a range?

}
}

pub fn in_range<R: RangeBounds<P::Value>>(self, range: R) -> InRange<P>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current behavior is if you do value_parser!(u16).range(1..)

  • It gets parsed as a i64 internally, causing more parse errors to be treated as range errors
  • The ranges compound with each other so you get 1..=u16::MAX

With the current implementation,

  • It doesn't allow narrowing the value's type, causing a regression in error messages
  • It doesn't merge the ranges

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm. For the second part, that could potentially be resolved by require T to implement a trait that exposes the maximum and minimum values. Although that would require the type to actually have a minimum and maximum value (or maybe it returns an Option?), and of course implement the trait for any meaningful data types, such as the integral and floating point types in the standard library.

The first part is more difficult though. If we wanted to restrict this to integers, then possibly the current implementation could be changed to use i128 and u128 on platforms that support it. But i'm not sure there is any garantee that those will be at least as big as isize and usize. It also doesn't allow specifying a range for f32 or f64. Nor would it really be able to support custom types that have an ordering (although I'm not sure how much of a need there is for that).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My original attempt at this had generic types for the parse type and the value type and required TryInto to be supported between them.

@epage
Copy link
Member

epage commented Jan 3, 2023

Any updates on this or #3895?

Still very rough, and needs a lot of work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants