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

Add a Rust example for the NVDA Controller Client #15771

Merged
merged 20 commits into from
Nov 30, 2023

Conversation

LeonarddeR
Copy link
Collaborator

@LeonarddeR LeonarddeR commented Nov 11, 2023

Link to issue number:

None

Summary of the issue:

The rust programming language is becoming more and more relevant, yet an example for the NVDA controller client is missing.

Description of user facing changes

None.

Description of development approach

Add a rust example, based on a workspace with two crates:

  • nvda-bindgen, containing the logic to create rust bindings based on nvdaController.h
  • nvda, rustified bindings to the nvda-bindgen crate

Testing strategy:

Test steps are in readme.md

Known issues with pull request:

This is blocked by #15734 for now.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@LeonarddeR
Copy link
Collaborator Author

@DataTriny Given your previous investment in NVDA Controller examples and you're much more experienced with Rust than I am, could you have a quick look at the code please?

@DataTriny
Copy link
Contributor

DataTriny commented Nov 11, 2023 via email

@LeonarddeR LeonarddeR marked this pull request as ready for review November 27, 2023 19:01
@LeonarddeR LeonarddeR requested a review from a team as a code owner November 27, 2023 19:01
@LeonarddeR LeonarddeR requested a review from seanbudd November 27, 2023 19:01
Copy link
Contributor

@DataTriny DataTriny left a comment

Choose a reason for hiding this comment

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

Minor suggestions from me. Looks good overall!

0
}

fn main() {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd try to have the main function return Result<()> and remove the calls to Result::unwrap in favor of the ? operator. The call to Result::expect can stay since it provides a clearer error message.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, good idea!

pub type OnSsmlMarkReached = onSsmlMarkReachedFuncType;

pub fn test_if_running() -> Result<()> {
let res = WIN32_ERROR(unsafe { nvdaController_testIfRunning() });
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you might be able to come up with a generic function to encapsulate your error handling logic and not repeat it everywhere right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, will do.

Ok(())
}

pub fn braille_message(mesage: &str) -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
pub fn braille_message(mesage: &str) -> Result<()> {
pub fn braille_message(message: &str) -> Result<()> {

}

pub fn braille_message(mesage: &str) -> Result<()> {
let message = HSTRING::from(mesage);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let message = HSTRING::from(mesage);
let message = HSTRING::from(message);

@seanbudd seanbudd added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label Nov 27, 2023
@seanbudd seanbudd marked this pull request as draft November 28, 2023 00:11
@LeonarddeR
Copy link
Collaborator Author

@DataTriny Thanks a lot for your review. I think I have addressed everything.

@LeonarddeR LeonarddeR marked this pull request as ready for review November 28, 2023 17:41

pub type OnSsmlMarkReached = onSsmlMarkReachedFuncType;

fn is_succes(error: u32) -> Result<()> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Sadly you have a typo here. Maybe to_result(status: u32) would be more appropriate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks, I'll rename accordingly.

pub type OnSsmlMarkReached = onSsmlMarkReachedFuncType;

fn is_succes(error: u32) -> Result<()> {
let res = WIN32_ERROR(error);
Copy link
Contributor

Choose a reason for hiding this comment

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

Having read windows-rs's doc, I think you should use WIN32_ERROR::ok instead of your if statement.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's a very good catch, thanks! Function can now be a one liner.

Copy link
Contributor

@DataTriny DataTriny left a comment

Choose a reason for hiding this comment

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

I think this is a good start for anyone interested in communicating with NVDA from a Rust program. Good job @LeonarddeR!

@LeonarddeR
Copy link
Collaborator Author

Thank you very much @DataTriny!

Copy link
Member

@seanbudd seanbudd left a comment

Choose a reason for hiding this comment

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

Note, I don't plan on reviewing the code itself, the only issue I picked up is with the code file licence headers

Comment on lines 1 to 3
// Copyright(C) 2023 NV Access Limited, Leonard de Ruijter
// This file is covered by the GNU Lesser General Public License, version 2.1.
// See the file license.txt for more details.
Copy link
Member

Choose a reason for hiding this comment

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

could you use the more standard python headers? we don't have a license.txt, we use "COPYING"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There is a license.txt in the controllerClient folder.

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternatively, if the mention of licence.txt is confusing, you can just use the copyright header for LGPL licensed code from our copyright headers wiki page

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks @lukaszgo1, I wasn't aware of these guidelines on the wiki.

@@ -125,6 +125,7 @@ Setting ``numCells`` is still supported for single line braille displays and ``n
- Device info yielded by ``hwPortUtils.listUsbDevices`` now contain the bus reported description of the USB device (key ``busReportedDeviceDescription``). (#15764, @LeonarddeR)
- For USB serial devices, ``bdDetect.getConnectedUsbDevicesForDriver`` and ``bdDetect.getDriversForConnectedUsbDevices`` now yield device matches containing a ``deviceInfo`` dictionary enriched with data about the USB device, such as ``busReportedDeviceDescription``. (#15764, @LeonarddeR)
- When the configuration file ``nvda.ini`` is corrupted, a backup copy is saved before it is reinitialized. (#15779, @CyrilleB79)
- Added an example to demonstrate using nvdaControllerClient.dll from Rust. (#15771, @LeonarddeR)
Copy link
Member

Choose a reason for hiding this comment

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

Could this be moved to "Changes to the NVDA Controller Client library:"

@seanbudd seanbudd merged commit 021c13d into nvaccess:master Nov 30, 2023
@nvaccessAuto nvaccessAuto added this to the 2024.1 milestone Nov 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. Controller
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants