2016-02-27 12:02:25 +00:00
|
|
|
# Conventions
|
|
|
|
|
|
|
|
In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust
|
|
|
|
constructs with minimal performance overhead, we follow the following
|
|
|
|
conventions.
|
|
|
|
|
|
|
|
Note that, thus far, not all the code follows these conventions and not all
|
|
|
|
conventions we try to follow have been documented here. If you find an instance
|
|
|
|
of either, feel free to remedy the flaw by opening a pull request with
|
|
|
|
appropriate changes or additions.
|
|
|
|
|
2016-07-22 21:37:51 +00:00
|
|
|
## Change Log
|
|
|
|
|
|
|
|
We follow the conventions laid out in [Keep A CHANGELOG][kacl].
|
|
|
|
|
|
|
|
[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
|
2016-02-27 12:02:25 +00:00
|
|
|
|
2016-02-29 19:26:05 +00:00
|
|
|
## libc constants, functions and structs
|
2016-02-27 12:02:25 +00:00
|
|
|
|
|
|
|
We do not define integer constants ourselves, but use or reexport them from the
|
|
|
|
[libc crate][libc].
|
|
|
|
|
2016-02-29 19:26:05 +00:00
|
|
|
We use the functions exported from [libc][libc] instead of writing our own
|
|
|
|
`extern` declarations.
|
|
|
|
|
|
|
|
We use the `struct` definitions from [libc][libc] internally instead of writing
|
2016-03-05 01:02:47 +00:00
|
|
|
our own. If we want to add methods to a libc type, we use the newtype pattern.
|
|
|
|
For example,
|
|
|
|
|
|
|
|
```rust
|
|
|
|
pub struct SigSet(libc::sigset_t);
|
|
|
|
|
|
|
|
impl SigSet {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
When creating newtypes, we use Rust's `CamelCase` type naming convention.
|
2016-02-27 12:02:25 +00:00
|
|
|
|
|
|
|
## Bitflags
|
2016-01-29 18:49:13 +00:00
|
|
|
|
Add libc_bitflags convenience macro
We define many bitflags types with values from the libc crate. Currently
these look like this:
bitflags!{
flags ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE,
const PROT_READ = libc::PROT_READ,
const PROT_WRITE = libc::PROT_WRITE,
const PROT_EXEC = libc::PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSUP = libc::PROT_GROWSUP,
}
}
There's some repetition which is tedious. With the new macro, the above
can instead be written
libc_bitflags!{
flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
Thanks to Daniel Keep for the Little Book of Rust Macros, and for
helping with this macro.
Refs https://github.com/nix-rust/nix/issues/264
2016-03-15 18:09:07 +00:00
|
|
|
Many C functions have flags parameters that are combined from constants using
|
|
|
|
bitwise operations. We represent the types of these parameters by types defined
|
|
|
|
using our `libc_bitflags!` macro, which is a convenience wrapper around the
|
|
|
|
`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
|
|
|
|
constant value from `libc`.
|
|
|
|
|
2016-02-29 19:21:39 +00:00
|
|
|
We name the type for a set of constants whose element's names start with `FOO_`
|
|
|
|
`FooFlags`.
|
2016-02-27 12:02:25 +00:00
|
|
|
|
Add libc_bitflags convenience macro
We define many bitflags types with values from the libc crate. Currently
these look like this:
bitflags!{
flags ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE,
const PROT_READ = libc::PROT_READ,
const PROT_WRITE = libc::PROT_WRITE,
const PROT_EXEC = libc::PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSUP = libc::PROT_GROWSUP,
}
}
There's some repetition which is tedious. With the new macro, the above
can instead be written
libc_bitflags!{
flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
Thanks to Daniel Keep for the Little Book of Rust Macros, and for
helping with this macro.
Refs https://github.com/nix-rust/nix/issues/264
2016-03-15 18:09:07 +00:00
|
|
|
For example,
|
|
|
|
|
|
|
|
```rust
|
|
|
|
libc_bitflags!{
|
2017-08-09 16:32:56 +00:00
|
|
|
pub struct ProtFlags: libc::c_int {
|
|
|
|
PROT_NONE;
|
|
|
|
PROT_READ;
|
|
|
|
PROT_WRITE;
|
|
|
|
PROT_EXEC;
|
Add libc_bitflags convenience macro
We define many bitflags types with values from the libc crate. Currently
these look like this:
bitflags!{
flags ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE,
const PROT_READ = libc::PROT_READ,
const PROT_WRITE = libc::PROT_WRITE,
const PROT_EXEC = libc::PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSUP = libc::PROT_GROWSUP,
}
}
There's some repetition which is tedious. With the new macro, the above
can instead be written
libc_bitflags!{
flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
Thanks to Daniel Keep for the Little Book of Rust Macros, and for
helping with this macro.
Refs https://github.com/nix-rust/nix/issues/264
2016-03-15 18:09:07 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
2017-08-09 16:32:56 +00:00
|
|
|
PROT_GROWSDOWN;
|
Add libc_bitflags convenience macro
We define many bitflags types with values from the libc crate. Currently
these look like this:
bitflags!{
flags ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE,
const PROT_READ = libc::PROT_READ,
const PROT_WRITE = libc::PROT_WRITE,
const PROT_EXEC = libc::PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSUP = libc::PROT_GROWSUP,
}
}
There's some repetition which is tedious. With the new macro, the above
can instead be written
libc_bitflags!{
flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
Thanks to Daniel Keep for the Little Book of Rust Macros, and for
helping with this macro.
Refs https://github.com/nix-rust/nix/issues/264
2016-03-15 18:09:07 +00:00
|
|
|
#[cfg(any(target_os = "linux", target_os = "android"))]
|
2017-08-09 16:32:56 +00:00
|
|
|
PROT_GROWSUP;
|
Add libc_bitflags convenience macro
We define many bitflags types with values from the libc crate. Currently
these look like this:
bitflags!{
flags ProtFlags: libc::c_int {
const PROT_NONE = libc::PROT_NONE,
const PROT_READ = libc::PROT_READ,
const PROT_WRITE = libc::PROT_WRITE,
const PROT_EXEC = libc::PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSDOWN = libc::PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
const PROT_GROWSUP = libc::PROT_GROWSUP,
}
}
There's some repetition which is tedious. With the new macro, the above
can instead be written
libc_bitflags!{
flags ProtFlags: libc::c_int {
PROT_NONE,
PROT_READ,
PROT_WRITE,
PROT_EXEC,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSDOWN,
#[cfg(any(target_os = "linux", target_os = "android"))]
PROT_GROWSUP,
}
}
Thanks to Daniel Keep for the Little Book of Rust Macros, and for
helping with this macro.
Refs https://github.com/nix-rust/nix/issues/264
2016-03-15 18:09:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2016-02-27 12:02:25 +00:00
|
|
|
|
|
|
|
## Enumerations
|
|
|
|
|
|
|
|
We represent sets of constants that are intended as mutually exclusive arguments
|
|
|
|
to parameters of functions by [enumerations][enum].
|
|
|
|
|
|
|
|
|
|
|
|
## Structures Initialized by libc Functions
|
|
|
|
|
|
|
|
Whenever we need to use a [libc][libc] function to properly initialize a
|
|
|
|
variable and said function allows us to use uninitialized memory, we use
|
|
|
|
[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized])
|
|
|
|
when defining the variable. This allows us to avoid the overhead incurred by
|
|
|
|
zeroing or otherwise initializing the variable.
|
|
|
|
|
|
|
|
[bitflags]: https://crates.io/crates/bitflags/
|
|
|
|
[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html
|
|
|
|
[enum]: https://doc.rust-lang.org/reference.html#enumerations
|
|
|
|
[libc]: https://crates.io/crates/libc/
|
|
|
|
[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
|