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

Added BaudRate enum for termios #518

Merged
merged 3 commits into from
Feb 25, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

### Added
- Added `::nix::sys::termios::BaudRate` enum to provide portable baudrate
values. ([#518](https://github.com/nix-rust/nix/pull/518))
- Added a new `WaitStatus::PtraceEvent` to support ptrace events on Linux
and Android ([([#438](https://github.com/nix-rust/nix/pull/438))
- Added support for POSIX AIO
Expand Down Expand Up @@ -41,6 +43,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
([#503](https://github.com/nix-rust/nix/pull/503))

### Changed
- `::nix::sys::termios::{cfgetispeed, cfsetispeed, cfgetospeed, cfsetospeed}`
switched to use `BaudRate` enum from `speed_t`.
([#518](https://github.com/nix-rust/nix/pull/518))
- `epoll_ctl` now could accept None as argument `event`
when op is `EpollOp::EpollCtlDel`.
([#480](https://github.com/nix-rust/nix/pull/480))
Expand Down
177 changes: 169 additions & 8 deletions src/sys/termios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,83 @@ mod ffi {
pub c_ospeed: speed_t
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BaudRate {
B0,
B50,
B75,
B110,
B134,
B150,
B200,
B300,
B600,
B1200,
B1800,
B2400,
B4800,
B9600,
B19200,
B38400,
B7200,
B14400,
B28800,
B57600,
B76800,
B115200,
B230400,
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
B460800,
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
B921600,
}

impl From<speed_t> for BaudRate {
fn from(s: speed_t) -> BaudRate {

use libc::{
B0, B50, B75, B110, B134, B150,
B200, B300, B600, B1200, B1800, B2400,
B4800, B9600, B19200, B38400,
B7200, B14400, B28800, B57600,
B76800, B115200, B230400};

#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
use libc::{B460800, B921600};

match s {
B0 => BaudRate::B0,
B50 => BaudRate::B50,
B75 => BaudRate::B75,
B110 => BaudRate::B110,
B134 => BaudRate::B134,
B150 => BaudRate::B150,
B200 => BaudRate::B200,
B300 => BaudRate::B300,
B600 => BaudRate::B600,
B1200 => BaudRate::B1200,
B1800 => BaudRate::B1800,
B2400 => BaudRate::B2400,
B4800 => BaudRate::B4800,
B9600 => BaudRate::B9600,
B19200 => BaudRate::B19200,
B38400 => BaudRate::B38400,
B7200 => BaudRate::B7200,
B14400 => BaudRate::B14400,
B28800 => BaudRate::B28800,
B57600 => BaudRate::B57600,
B76800 => BaudRate::B76800,
B115200 => BaudRate::B115200,
B230400 => BaudRate::B230400,
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
B460800 => BaudRate::B460800,
#[cfg(any(target_os = "netbsd", target_os = "freebsd"))]
B921600 => BaudRate::B921600,
b @ _ => unreachable!("Invalid baud constant: {}", b),
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this arm is necessary. The compiler should be able to reason about this branch not being reachable and generate a compile error if something is off (which is better than this runtime error).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it needs to be there to cover all branch cases. speed_t is just an alias to something like c_uint so you need a catch-all case at the end to cover all possible values of c_uint.

For example, if you remove the similar case for the linux group of constants at line 452 you'll get the compile error:

   Compiling nix v0.8.0 (file:///home/zac/repos/rust/nix)
error[E0004]: non-exhaustive patterns: `_` not covered
   --> /home/zac/repos/rust/nix/src/sys/termios.rs:420:23
    |
419 |                 match s {
    |                       ^ pattern `_` not covered

error: aborting due to previous error

error: Could not compile `nix`.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, yeah. You are right.

}
}
}

pub const VEOF: usize = 0;
pub const VEOL: usize = 1;
pub const VEOL2: usize = 2;
Expand Down Expand Up @@ -293,6 +370,90 @@ mod ffi {
pub c_ospeed: speed_t
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BaudRate {
B0,
B50,
B75,
B110,
B134,
B150,
B200,
B300,
B600,
B1200,
B1800,
B2400,
B4800,
B9600,
B19200,
B38400,
B57600,
B115200,
B230400,
B460800,
B500000,
B576000,
B921600,
B1000000,
B1152000,
B1500000,
B2000000,
B2500000,
B3000000,
B3500000,
B4000000,
}

impl From<speed_t> for BaudRate {
fn from(s: speed_t) -> BaudRate {

use libc::{
B0, B50, B75, B110, B134, B150,
B200, B300, B600, B1200, B1800, B2400,
B4800, B9600, B19200, B38400, B57600,
B115200, B230400, B460800, B500000,
B576000, B921600, B1000000, B1152000,
B1500000, B2000000, B2500000, B3000000,
B3500000, B4000000};

match s {
B0 => BaudRate::B0,
B50 => BaudRate::B50,
B75 => BaudRate::B75,
B110 => BaudRate::B110,
B134 => BaudRate::B134,
B150 => BaudRate::B150,
B200 => BaudRate::B200,
B300 => BaudRate::B300,
B600 => BaudRate::B600,
B1200 => BaudRate::B1200,
B1800 => BaudRate::B1800,
B2400 => BaudRate::B2400,
B4800 => BaudRate::B4800,
B9600 => BaudRate::B9600,
B19200 => BaudRate::B19200,
B38400 => BaudRate::B38400,
B57600 => BaudRate::B57600,
B115200 => BaudRate::B115200,
B230400 => BaudRate::B230400,
B460800 => BaudRate::B460800,
B500000 => BaudRate::B500000,
B576000 => BaudRate::B576000,
B921600 => BaudRate::B921600,
B1000000 => BaudRate::B1000000,
B1152000 => BaudRate::B1152000,
B1500000 => BaudRate::B1500000,
B2000000 => BaudRate::B2000000,
B2500000 => BaudRate::B2500000,
B3000000 => BaudRate::B3000000,
B3500000 => BaudRate::B3500000,
B4000000 => BaudRate::B4000000,
b @ _ => unreachable!("Invalid baud constant: {}", b),
}
}
}

pub const VEOF: usize = 4;
pub const VEOL: usize = 11;
pub const VEOL2: usize = 16;
Expand Down Expand Up @@ -426,27 +587,27 @@ mod ffi {
}
}

pub fn cfgetispeed(termios: &Termios) -> speed_t {
pub fn cfgetispeed(termios: &Termios) -> BaudRate {
unsafe {
ffi::cfgetispeed(termios)
ffi::cfgetispeed(termios).into()
}
}

pub fn cfgetospeed(termios: &Termios) -> speed_t {
pub fn cfgetospeed(termios: &Termios) -> BaudRate {
unsafe {
ffi::cfgetospeed(termios)
ffi::cfgetospeed(termios).into()
}
}

pub fn cfsetispeed(termios: &mut Termios, speed: speed_t) -> Result<()> {
pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
Errno::result(unsafe {
ffi::cfsetispeed(termios, speed)
ffi::cfsetispeed(termios, baud as speed_t)
}).map(drop)
}

pub fn cfsetospeed(termios: &mut Termios, speed: speed_t) -> Result<()> {
pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
Errno::result(unsafe {
ffi::cfsetospeed(termios, speed)
ffi::cfsetospeed(termios, baud as speed_t)
}).map(drop)
}

Expand Down