Skip to content

Add From and TryFrom impls in libc_enum macro #1088

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

Closed
wants to merge 11 commits into from

Conversation

frangio
Copy link
Contributor

@frangio frangio commented Jun 16, 2019

This PR adds From and TryFrom impls in libc_enum. The macro was rewritten from scratch, and I think it's considerably simpler now. The syntax changed slightly in order to add the "base" type for which it'll generate conversion impls. It looks more like bitflags now.

To support Rust versions where TryFrom isn't stable and keep the current MSRV, there is an inherent try_from method. I had to add a build dependency on the version_check crate to support conditionally compiling the trait impl.

When try_from fails it returns Error::invalid_argument(). I copied this over from an existing Signal::from_c_int function, but I'm not sure it's the right error to use. Should we add a new Error variant?

Copy link
Member

@asomers asomers left a comment

Choose a reason for hiding this comment

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

It certainly is simpler than the old one. I like. I just have a few concerns inline.

src/macros.rs Outdated
attrs: $attrs,
entries: $entries,
}
@(pub)
Copy link
Member

Choose a reason for hiding this comment

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

What is the function of the @ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, it's just denoting that this is an internal rule.

$(#[$enum_attr:meta])*
enum $enum:ident : $prim:ty {
$(
$(#[doc = $var_doc:tt])*
Copy link
Member

Choose a reason for hiding this comment

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

Doc strings and cfg attributes are both different kinds of attributes. Could you simplify the macro by combining these two lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The compiler emits a warning for "unused doc comment" when it sees a doc comment annotating a match arm, so I match them separately here so that I can use the cfg attributes on their own later.

$(
$(#[doc = $var_doc])*
$(#[cfg($var_cfg)])*
$entry = ::libc::$entry as isize
Copy link
Member

Choose a reason for hiding this comment

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

why cast to isize? It seems like $prim would be more appropriate.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

isize is the type that rust expects here. I tried using $prim, but that requires adding a #[repr($prim)] attribute to the enum, which I couldn't get to work for some reason I unfortunately can't remember.

Copy link
Member

Choose a reason for hiding this comment

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

Given the way that these types will be used, I think that #[repr($prim)] would be better. Could you try again to make it work? Show me the error if you have trouble.

Copy link
Contributor Author

@frangio frangio Jun 28, 2019

Choose a reason for hiding this comment

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

The problem is that in some places we're using a custom type as $prim, and it turns out the repr attribute only works with simple unsigned or signed integer types u* and i* (see the Rustonomicon).

The reason we need to use a custom type is that in some cases the underlying type depends on the target machine. I'm not sure how we could get around that with the enum Signal : c_int syntax I set up here.

Given the way that these types will be used

Can you share an example where the repr makes a difference?

$(#[cfg($var_cfg)])*
::libc::$entry => Ok($enum::$entry),
)*
// don't think this Error is the correct one
Copy link
Member

Choose a reason for hiding this comment

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

I think that's a fine choice of error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason I doubt is that Error::Sys(Errno::EINVAL) probably makes one think this is a "system error" that was picked up from errno.

How about adding an Error::InvalidConversion?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I understand. Error::InvalidConversion would work, too.

@frangio
Copy link
Contributor Author

frangio commented Jun 17, 2019

Fixed some of the review items and rebased on master.

@asomers
Copy link
Member

asomers commented Jul 1, 2019

It looks like your build is failing on our MSRV, which is Rust 1.25.0. could you please fix it?

@frangio frangio closed this Feb 24, 2023
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.

2 participants