1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-07-03 05:27:04 +02:00

Format all Markdown files with dprint (#1157)

This is the result of running `dprint fmt` after removing `src/` from
the list of excluded directories.

This also reformats the Rust code: we might want to tweak this a bit in
the future since some of the changes removes the hand-formatting. Of
course, this formatting can be seen as a mis-feature, so maybe this is
good overall.

Thanks to mdbook-i18n-helpers 0.2, the POT file is nearly unchanged
after this, meaning that all existing translations remain valid! A few
messages were changed because of stray whitespace characters:

     msgid ""
     "Slices always borrow from another object. In this example, `a` has to remain "
    -"'alive' (in scope) for at least as long as our slice. "
    +"'alive' (in scope) for at least as long as our slice."
     msgstr ""

The formatting is enforced in CI and we will have to see how annoying
this is in practice for the many contributors. If it becomes annoying,
we should look into fixing dprint/check#11 so that `dprint` can annotate
the lines that need fixing directly, then I think we can consider more
strict formatting checks.

I added more customization to `rustfmt.toml`. This is to better emulate
the dense style used in the course:

- `max_width = 85` allows lines to take up the full width available in
our code blocks (when taking margins and the line numbers into account).
- `wrap_comments = true` ensures that we don't show very long comments
in the code examples. I edited some comments to shorten them and avoid
unnecessary line breaks — please trim other unnecessarily long comments
when you see them! Remember we're writing code for slides 😄
- `use_small_heuristics = "Max"` allows for things like struct literals
and if-statements to take up the full line width configured above.

The formatting settings apply to all our Rust code right now — I think
we could improve this with https://github.com/dprint/dprint/issues/711
which lets us add per-directory `dprint` configuration files. However,
the `inherit: true` setting is not yet implemented (as far as I can
tell), so a nested configuration file will have to copy most or all of
the top-level file.
This commit is contained in:
Martin Geisler
2023-12-31 00:15:07 +01:00
committed by GitHub
parent f43e72e0ad
commit c9f66fd425
302 changed files with 3067 additions and 2622 deletions

View File

@ -1,7 +1,9 @@
# AIDL
The [Android Interface Definition Language
(AIDL)](https://developer.android.com/guide/components/aidl) is supported in Rust:
The
[Android Interface Definition Language
(AIDL)](https://developer.android.com/guide/components/aidl) is supported in
Rust:
* Rust code can call existing AIDL servers,
* You can create new AIDL servers in Rust.
- Rust code can call existing AIDL servers,
- You can create new AIDL servers in Rust.

View File

@ -20,15 +20,14 @@ use com_example_birthdayservice::binder;
const SERVICE_IDENTIFIER: &str = "birthdayservice";
/// Connect to the BirthdayService.
pub fn connect() -> Result<binder::Strong<dyn IBirthdayService>, binder::StatusCode> {
pub fn connect() -> Result<binder::Strong<dyn IBirthdayService>, binder::StatusCode>
{
binder::get_interface(SERVICE_IDENTIFIER)
}
/// Call the birthday service.
fn main() -> Result<(), binder::Status> {
let name = std::env::args()
.nth(1)
.unwrap_or_else(|| String::from("Bob"));
let name = std::env::args().nth(1).unwrap_or_else(|| String::from("Bob"));
let years = std::env::args()
.nth(2)
.and_then(|arg| arg.parse::<i32>().ok())

View File

@ -24,8 +24,6 @@ impl binder::Interface for BirthdayService {}
impl IBirthdayService for BirthdayService {
fn wishHappyBirthday(&self, name: &str, years: i32) -> binder::Result<String> {
Ok(format!(
"Happy Birthday {name}, congratulations with the {years} years!"
))
Ok(format!("Happy Birthday {name}, congratulations with the {years} years!"))
}
}

View File

@ -2,13 +2,13 @@
Finally, we can create a Rust client for our new service.
*birthday_service/src/client.rs*:
_birthday_service/src/client.rs_:
```rust,ignore
{{#include birthday_service/src/client.rs:main}}
```
*birthday_service/Android.bp*:
_birthday_service/Android.bp_:
```javascript
{{#include birthday_service/Android.bp:birthday_client}}

View File

@ -2,13 +2,13 @@
We can now implement the AIDL service:
*birthday_service/src/lib.rs*:
_birthday_service/src/lib.rs_:
```rust,ignore
{{#include birthday_service/src/lib.rs:IBirthdayService}}
```
*birthday_service/Android.bp*:
_birthday_service/Android.bp_:
```javascript
{{#include birthday_service/Android.bp:libbirthdayservice}}

View File

@ -2,13 +2,13 @@
You declare the API of your service using an AIDL interface:
*birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl*:
_birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl_:
```java
{{#include birthday_service/aidl/com/example/birthdayservice/IBirthdayService.aidl:IBirthdayService}}
```
*birthday_service/aidl/Android.bp*:
_birthday_service/aidl/Android.bp_:
```javascript
{{#include birthday_service/aidl/Android.bp}}

View File

@ -2,13 +2,13 @@
Finally, we can create a server which exposes the service:
*birthday_service/src/server.rs*:
_birthday_service/src/server.rs_:
```rust,ignore
{{#include birthday_service/src/server.rs:main}}
```
*birthday_service/Android.bp*:
_birthday_service/Android.bp_:
```javascript
{{#include birthday_service/Android.bp:birthday_server}}

View File

@ -19,13 +19,20 @@ We will look at `rust_binary` and `rust_library` next.
Additional items speaker may mention:
- Cargo is not optimized for multi-language repos, and also downloads packages from the internet.
- Cargo is not optimized for multi-language repos, and also downloads packages
from the internet.
- For compliance and performance, Android must have crates in-tree. It must also interop with C/C++/Java code. Soong fills that gap.
- For compliance and performance, Android must have crates in-tree. It must also
interop with C/C++/Java code. Soong fills that gap.
- Soong has many similarities to Bazel, which is the open-source variant of Blaze (used in google3).
- Soong has many similarities to Bazel, which is the open-source variant of
Blaze (used in google3).
- There is a plan to transition [Android](https://source.android.com/docs/setup/build/bazel/introduction), [ChromeOS](https://chromium.googlesource.com/chromiumos/bazel/), and [Fuchsia](https://source.android.com/docs/setup/build/bazel/introduction) to Bazel.
- There is a plan to transition
[Android](https://source.android.com/docs/setup/build/bazel/introduction),
[ChromeOS](https://chromium.googlesource.com/chromiumos/bazel/), and
[Fuchsia](https://source.android.com/docs/setup/build/bazel/introduction) to
Bazel.
- Learning Bazel-like build rules is useful for all Rust OS developers.

View File

@ -4,8 +4,8 @@ You use `rust_library` to create a new Rust library for Android.
Here we declare a dependency on two libraries:
* `libgreeting`, which we define below,
* `libtextwrap`, which is a crate already vendored in
- `libgreeting`, which we define below,
- `libtextwrap`, which is a crate already vendored in
[`external/rust/crates/`][crates].
[crates]: https://cs.android.com/android/platform/superproject/+/master:external/rust/crates/

View File

@ -3,8 +3,8 @@
Rust has excellent support for interoperability with other languages. This means
that you can:
* Call Rust functions from other languages.
* Call functions written in other languages from Rust.
- Call Rust functions from other languages.
- Call functions written in other languages from Rust.
When you call functions in a foreign language we say that you're using a
_foreign function interface_, also known as FFI.

View File

@ -17,12 +17,12 @@ cc_library_static {
<details>
* Point out that `libcxx_test_bridge_header` and `libcxx_test_bridge_code` are
- Point out that `libcxx_test_bridge_header` and `libcxx_test_bridge_code` are
the dependencies for the CXX-generated C++ bindings. We'll show how these are
setup on the next slide.
* Note that you also need to depend on the `cxx-bridge-header` library in order
- Note that you also need to depend on the `cxx-bridge-header` library in order
to pull in common CXX definitions.
* Full docs for using CXX in Android can be found in [the Android docs]. You may
- Full docs for using CXX in Android can be found in [the Android docs]. You may
want to share that link with the class so that students know where they can
find these instructions again in the future.

View File

@ -26,9 +26,9 @@ genrule {
<details>
* The `cxxbridge` tool is a standalone tool that generates the C++ side of the
- The `cxxbridge` tool is a standalone tool that generates the C++ side of the
bridge module. It is included in Android and available as a Soong tool.
* By convention, if your Rust source file is `lib.rs` your header file will be
- By convention, if your Rust source file is `lib.rs` your header file will be
named `lib.rs.h` and your source file will be named `lib.rs.cc`. This naming
convention isn't enforced, though.

View File

@ -10,14 +10,14 @@ a Rust module annotated with the `#[cxx::bridge]` attribute macro.
<details>
* The bridge is generally declared in an `ffi` module within your crate.
* From the declarations made in the bridge module, CXX will generate matching
- The bridge is generally declared in an `ffi` module within your crate.
- From the declarations made in the bridge module, CXX will generate matching
Rust and C++ type/function definitions in order to expose those items to both
languages.
* To view the generated Rust code, use [cargo-expand] to view the expanded proc
- To view the generated Rust code, use [cargo-expand] to view the expanded proc
macro. For most of the examples you would use `cargo expand ::ffi` to expand
just the `ffi` module (though this doesn't apply for Android projects).
* To view the generated C++ code, look in `target/cxxbridge`.
- To view the generated C++ code, look in `target/cxxbridge`.
[cargo-expand]: https://github.com/dtolnay/cargo-expand

View File

@ -43,10 +43,10 @@ impl BlobstoreClient {
<details>
* The programmer does not need to promise that the signatures they have typed in
- The programmer does not need to promise that the signatures they have typed in
are accurate. CXX performs static assertions that the signatures exactly
correspond with what is declared in C++.
* `unsafe extern` blocks allow you to declare C++ functions that are safe to
- `unsafe extern` blocks allow you to declare C++ functions that are safe to
call from Rust.
</details>

View File

@ -6,9 +6,9 @@
<details>
* C++ functions declared to return a `Result` will catch any thrown exception on
- C++ functions declared to return a `Result` will catch any thrown exception on
the C++ side and return it as an `Err` value to the calling Rust function.
* If an exception is thrown from an extern "C++" function that is not declared
- If an exception is thrown from an extern "C++" function that is not declared
by the CXX bridge to return `Result`, the program calls C++'s
`std::terminate`. The behavior is equivalent to the same exception being
thrown through a `noexcept` C++ function.

View File

@ -6,9 +6,9 @@
<details>
* Items declared in the `extern "Rust"` reference items that are in scope in the
- Items declared in the `extern "Rust"` reference items that are in scope in the
parent module.
* The CXX code generator uses your `extern "Rust"` section(s) to produce a C++
- The CXX code generator uses your `extern "Rust"` section(s) to produce a C++
header file containing the corresponding C++ declarations. The generated
header has the same path as the Rust source file containing the bridge, except
with a .rs.h file extension.

View File

@ -6,12 +6,12 @@
<details>
* Rust functions that return `Result` are translated to exceptions on the C++
- Rust functions that return `Result` are translated to exceptions on the C++
side.
* The exception thrown will always be of type `rust::Error`, which primarily
- The exception thrown will always be of type `rust::Error`, which primarily
exposes a way to get the error message string. The error message will come
from the error type's `Display` impl.
* A panic unwinding from Rust to C++ will always cause the process to
- A panic unwinding from Rust to C++ will always cause the process to
immediately terminate.
</details>

View File

@ -18,7 +18,7 @@ Generated C++:
<details>
* On the Rust side, the code generated for shared enums is actually a struct
- On the Rust side, the code generated for shared enums is actually a struct
wrapping a numeric value. This is because it is not UB in C++ for an enum
class to hold a value different from all of the listed variants, and our Rust
representation needs to have the same behavior.

View File

@ -6,8 +6,8 @@
<details>
* Only C-like (unit) enums are supported.
* A limited number of traits are supported for `#[derive()]` on shared types.
- Only C-like (unit) enums are supported.
- A limited number of traits are supported for `#[derive()]` on shared types.
Corresponding functionality is also generated for the C++ code, e.g. if you
derive `Hash` also generates an implementation of `std::hash` for the
corresponding C++ type.

View File

@ -1,7 +1,7 @@
# Additional Types
| Rust Type | C++ Type |
|-------------------|----------------------|
| ----------------- | -------------------- |
| `String` | `rust::String` |
| `&str` | `rust::Str` |
| `CxxString` | `std::string` |
@ -13,14 +13,14 @@
<details>
* These types can be used in the fields of shared structs and the arguments and
- These types can be used in the fields of shared structs and the arguments and
returns of extern functions.
* Note that Rust's `String` does not map directly to `std::string`. There are a
- Note that Rust's `String` does not map directly to `std::string`. There are a
few reasons for this:
* `std::string` does not uphold the UTF-8 invariant that `String` requires.
* The two types have different layouts in memory and so can't be passed
- `std::string` does not uphold the UTF-8 invariant that `String` requires.
- The two types have different layouts in memory and so can't be passed
directly between languages.
* `std::string` requires move constructors that don't match Rust's move
- `std::string` requires move constructors that don't match Rust's move
semantics, so a `std::string` can't be passed by value to Rust.
</details>

View File

@ -1,8 +1,9 @@
# Interoperability with Java
Java can load shared objects via [Java Native Interface
(JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface). The [`jni`
crate](https://docs.rs/jni/) allows you to create a compatible library.
Java can load shared objects via
[Java Native Interface (JNI)](https://en.wikipedia.org/wiki/Java_Native_Interface).
The [`jni` crate](https://docs.rs/jni/) allows you to create a compatible
library.
First, we create a Rust function to export to Java:

View File

@ -17,8 +17,8 @@ fn main() {
}
```
We already saw this in the [Safe FFI Wrapper
exercise](../../exercises/day-3/safe-ffi-wrapper.md).
We already saw this in the
[Safe FFI Wrapper exercise](../../exercises/day-3/safe-ffi-wrapper.md).
> This assumes full knowledge of the target platform. Not recommended for
> production.

View File

@ -17,4 +17,3 @@ _interoperability/c/libbirthday/libbirthday.c_:
```c
{{#include c/libbirthday/libbirthday.c}}
```

View File

@ -19,10 +19,7 @@ use birthday_bindgen::{card, print_card};
fn main() {
let name = std::ffi::CString::new("Peter").unwrap();
let card = card {
name: name.as_ptr(),
years: 42,
};
let card = card { name: name.as_ptr(), years: 42 };
// SAFETY: `print_card` is safe to call with a valid `card` pointer.
unsafe {
print_card(&card as *const card);

View File

@ -14,8 +14,8 @@ fn main() {
}
```
We already saw this in the [Safe FFI Wrapper
exercise](../../exercises/day-3/safe-ffi-wrapper.md).
We already saw this in the
[Safe FFI Wrapper exercise](../../exercises/day-3/safe-ffi-wrapper.md).
> This assumes full knowledge of the target platform. Not recommended for
> production.

View File

@ -34,7 +34,6 @@ _interoperability/rust/analyze/Android.bp_
{{#include rust/analyze/Android.bp}}
```
Build, push, and run the binary on your device:
```shell
@ -43,7 +42,8 @@ Build, push, and run the binary on your device:
<details>
`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will just be the name of
the function. You can also use `#[export_name = "some_name"]` to specify whatever name you want.
`#[no_mangle]` disables Rust's usual name mangling, so the exported symbol will
just be the name of the function. You can also use
`#[export_name = "some_name"]` to specify whatever name you want.
</details>

View File

@ -1,7 +1,7 @@
# Setup
We will be using a Cuttlefish Android Virtual Device to test our code. Make sure you
have access to one or create a new one with:
We will be using a Cuttlefish Android Virtual Device to test our code. Make sure
you have access to one or create a new one with:
```shell
source build/envsetup.sh
@ -9,15 +9,18 @@ lunch aosp_cf_x86_64_phone-trunk_staging-userdebug
acloud create
```
Please see the [Android Developer
Codelab](https://source.android.com/docs/setup/start) for details.
Please see the
[Android Developer Codelab](https://source.android.com/docs/setup/start) for
details.
<details>
Key points:
- Cuttlefish is a reference Android device designed to work on generic Linux desktops. MacOS support is also planned.
- Cuttlefish is a reference Android device designed to work on generic Linux
desktops. MacOS support is also planned.
- The Cuttlefish system image maintains high fidelity to real devices, and is the ideal emulator to run many Rust use cases.
- The Cuttlefish system image maintains high fidelity to real devices, and is
the ideal emulator to run many Rust use cases.
</details>