summaryrefslogtreecommitdiffstats
path: root/docs/writing-rust-code/basics.md
blob: 651f24f8b9b7be37c379e9a3db1d108459f5c273 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Basics

## Formatting Rust code

To format all the Rust code within a directory `$DIR`, run:
```
./mach lint -l rustfmt --fix $DIR
```

## Using Cargo

Many Cargo commands can be run on individual crates. Change into the directory
containing the crate's `Cargo.toml` file, and then run the command with
`MOZ_TOPOBJDIR` set appropriately. For example, to generate and view rustdocs
for the `xpcom` crate, run these commands:

```
cd xpcom/rust/xpcom
MOZ_TOPOBJDIR=$OBJDIR cargo doc
cd -
firefox target/doc/xpcom/index.html
```
where `$OBJDIR` is the path to the object directory.

## Using static prefs

Static boolean/integer prefs can be easily accessed from Rust code. Add a
`rust: true` field to the pref definition in
[modules/libpref/init/StaticPrefList.yaml](https://searchfox.org/mozilla-central/source/modules/libpref/init/StaticPrefList.yaml),
like this:
```yaml
- name: my.lucky.pref
  type: RelaxedAtomicBool
  value: true
  mirror: always
  rust: true
```
The pref can then be accessed via the `pref!` macro, like this:
```
let my_lucky_pref = static_prefs::pref!("my.lucky.pref");
```

## Helper crates

The following in-tree helper crates provide idiomatic support for some common patterns.
- [nserror](https://searchfox.org/mozilla-central/source/xpcom/rust/nserror/src/lib.rs)
reflects `nsresult` codes into Rust.
- [nsstring](https://searchfox.org/mozilla-central/source/xpcom/rust/nsstring/src/lib.rs)
  exposes bindings for XPCOM string types. You can use the same `ns{A,C}String`
  types as C++ for owned strings and pass them back and forth over the
  boundary. There is also `ns{A,C}Str` for dependent or borrowed strings.
- [thin-vec](https://docs.rs/thin-vec/latest/thin_vec/) provides a
  Rust `Vec`-like type that is layout-compatible with Gecko's `nsTArray`.
- [xpcom](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/src)
  provides multiple building blocks for a component's implementation.
  - The `RefPtr` type is for managing reference-counted pointers.
  - XPCOM component getters are generated by
    [xpcom/components/gen_static_components.py](https://searchfox.org/mozilla-central/source/xpcom/components/gen_static_components.py),
    and can be called like this:
    ```
    use xpcom::{interfaces::nsIPrefService, RefPtr};
    let pref_service: RefPtr<nsIPrefService> = xpcom::components::Preferences::service()?;
    ```
  - There is also a `get_service` function that works like `do_GetService` in
    C++, as an alternative.
  - A set of `derive` macros help with declaring interface implementations. The
    [docs](https://searchfox.org/mozilla-central/source/xpcom/rust/xpcom/xpcom_macros/src/lib.rs)
    have details and examples.
- [moz_task](https://searchfox.org/mozilla-central/source/xpcom/rust/moz_task/src/lib.rs)
  wraps XPCOM's threading functions in order to make it easy and safe to write
  threaded code. It has helpers for getting and creating threads, dispatching
  async runnables, and thread-safe handles.
- [storage](https://searchfox.org/mozilla-central/source/storage/rust/src/lib.rs)
  is an interface to mozStorage, our wrapper for SQLite. It can wrap an
  existing storage connection, and prepare and execute statements. This crate
  wraps the synchronous connection API, and lets you execute statements
  asynchronously via `moz_task`.
- [storage_variant](https://searchfox.org/mozilla-central/source/storage/variant/src/lib.rs)
  is for working with variants. It also provides a `HashPropertyBag` type
  that's useful for passing hash maps over XPCOM to JS.

Unfortunately, rustdocs are [not yet generated and
hosted](https://bugzilla.mozilla.org/show_bug.cgi?id=1428139) for crates within
mozilla-central. Therefore, the crate links shown above link to files
containing the relevant rustdocs source where possible. However, you can
generate docs locally using the `cargo doc` command described above.