-
Notifications
You must be signed in to change notification settings - Fork 497
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
Implement BSTR
and PWSTR
using platform-agnostic widestring
crate
#800
Conversation
#[cfg(windows)] | ||
unsafe { | ||
SysAllocStringLen( | ||
super::SystemServices::PWSTR(value.as_ptr() as _), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think OLECHAR *
should be considered as PWSTR
, but alas.
let value: ::std::vec::Vec<u16> = value.encode_utf16().collect(); | ||
// TODO: This allocates+copies twice. | ||
let value = ::windows::widestring::WideString::from_str(value); | ||
Self::from_wide(&value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't think we can perform the conversion at once, assuming we really want to use SysAllocStringLen
to get a proper length-prefixed string without being able to do the conversion in-place.
@@ -3,46 +3,88 @@ use super::*; | |||
pub fn gen_pwstr() -> TokenStream { | |||
quote! { | |||
#[repr(transparent)] | |||
#[derive(::std::clone::Clone, ::std::marker::Copy, ::std::cmp::Eq, ::std::fmt::Debug)] | |||
pub struct PWSTR(pub *mut u16); | |||
#[derive(::std::clone::Clone, ::std::marker::Copy, ::std::cmp::Eq)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What are the ownership semantics around PWSTR
pointers and cloning/copying? This doesn't seem correct 😬
let other = unsafe { ::windows::widestring::WideCString::from_str_unchecked(other) }; | ||
self.as_wide().eq(&other) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that as_wide
performs null-checking on the self
-pointer already (and panics), an unchecked string with interior nulls will never be equal. Perhaps better to remain on the safe side (from_str() -> Result
) and map the error to false
instead?
Implemented it this way in the last commit (but it breaks the Linux implementation for now, even though it should make overriding functions easier in the end, as long as they are publicly exported and disallowed from the generator). Let me know what you think, if we end up going this route I'll reorder the PR to apply that commit first - and put it in a separate PR. |
5912f56
to
1a15dc0
Compare
Sorry for the delay - been heads down working on #81. I'll take a look hopefully soon. Just a quick caution, those types were previously part of the Windows crate but it doesn't really scale to include them - where does it end? I realize its simpler that way but I'd like to simplify the way that types like this are extended in the generated bindings instead. Basically the rule is that types have to be defined in the Windows crate if and only if they are used by both WinRT and Win32 APIs and thus need a canonical definition. |
Can you clarify what "doesn't scale"? The same applies to the current generation overloads, those files and lists may explode over time too. Do you mean namespaces? We can easily fix that by moving these types into the desired (as per metadata) namespace, and we can/should also reexport them from generated bindings instead of having these live somewhere in
I still feel like not emitting completely static code to a generated file is a win, in particular because this also allows both autoformatting and development environments like |
It doesn't scale in the sense that there is an never-ending list of types that someone will feel deserves some form of extension and incorporation in the Windows crate. Its BSTR now, VARIANT tomorrow, a few D2D types the next, a few dozen D3D types, and so on. There's an admittedly fine line between what's core to most/all APIs and what can and should exist as specialized and idiomatic Rust wrapper library crates. I'm still working through where that line is, but I'd like to be cautious about just lumping too many nice-to-haves in the Windows crate as it can become a maintenance and support burden that is not easily managed. Ideally it could be driven entirely from metadata, but the Win32 metadata isn't nearly as rich and descriptive as that of WinRT. |
It feels pointless to discuss where these types should reside as I really don't care. Put them in a separate crate for all you want. Rather, we should discuss the main problem I see in the current approach and whether that's something you're willing to solve in the first place. Repeating that, it's quite simply formulated as: don't put static blocks of code (not influenced by external variables) in For now I've removed this commit as it has little relevance to That said again, all the overrides moved by this implementation are already defined somewhere in this repository. Whether the override sits in the Windows crate or |
I appreciate some of these goals but this PR is pushing the Windows crate too far in different areas. Feel free to open and discuss the individual issues further. |
Closing PRs with associated conversational effort for sure isn't the right way to get that started. But it's an easy way to cut off a conversation. |
This PR should have been preceded by an issue discussion. I'm sorry I didn't make that clear earlier. I love your work and enthusiasm but design changes need to be carefully considered as there are often conflicting requirements in a project of this nature. |
That is a fair point and largely backed by me pushing to move static code outside of If we can go back to the actual subject here - After all, I needed to write this to test if windows-rs would be viable for my intended usecase (which it totally
You closed every single one of my open PRs and issues within an hour or so, that seems pretty contradictory. How can I be reassured that won't happen again when I "Feel free to open and discuss the individual issues further"? |
I'm sorry I didn't get around to commenting on widestring. I've been rather swamped and its not easy to find the time explore every suggestion. I haven't had a chance to look at the widestring crate. I'm generally weary of taking on additional dependencies. There are also quite a few open issues already having to do with string support and I have to consider how best to handle them all in a consistent, scalable, and complementary way. It's not a simple problem and not one I have the time for right now - I have other urgent priorities. I will however not likely do much more with strings until I've had the time to consider a more holistic solution to the problem. I don't really mind whether you want to raise issues with a PR if it helps to illustrate or comment on code. But ultimately, I need to make the call on whether suggestions/issues/contributions/PRs are in the best interest of the project. And if they're not I'm going to eventually close them because not closing them gives the false impression that the specific issue or contribution is still open for consideration. Cross-platform support for example. Feel free to disagree, open new issues or PRs, or refine suggestions on your own before coming back for more feedback. This is a big project and I'm doing my best to manage it while also being the primary contributor. Thanks for your patience. |
Widestrings are UTF-16 on Windows but UTF-32 on other platforms. The
widestring
crate abstracts this detail away behind itsWideString
,WideCString
,WideStr
andWideCStr
type aliases for convenience. Aside that it provides useful helpers and makes a clear distinction between null-terminated strings and "binary strings" with an explicit length and interior NULLs.The only downside of
widestring
is that it includeswinapi
underdev-dependencies
for an example in the documentation.This change adds some missing value comparison, debugging and printing functionality.
TODO
Shims for non-Windows platforms are not ready. They're in a separate commit and best reviewed (and PR'd) separately, but it'd be nice if we can discuss how to override the
Sys*
functions themselves. see also #770.crates/gen/src/types
ergonomicsEditing these massive generated
quote!
blocks is really cumbersome without autoformatting andrust-analyzer
. Are there plans to promote these types to thewindows
crate (likeHRESULT
andIUnknown
)? That makes editing easier and slims down all autogenerated files by a fair bit.