diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8f3978b..c91220b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -28,10 +28,26 @@ jobs: with: command: test args: --workspace --all-targets --color=always --features serde,unix + - name: Clippy + uses: actions-rs-plus/clippy-check@v2.1.1 + with: + args: --workspace --all-targets --features serde,unix - clippy: - name: Clippy + check_configurations: + name: Check codebase runs-on: ubuntu-latest + env: + RUSTFLAGS: "-D warnings" + RUSTDOCFLAGS: "-D warnings" + strategy: + matrix: + target: + - "x86_64-unknown-linux-gnu" + - "aarch64-unknown-linux-gnu" + - "x86_64-pc-windows-msvc" + - "x86_64-apple-darwin" + - "x86_64-unknown-freebsd" + - "x86_64-unknown-netbsd" steps: - name: Checkout code uses: actions/checkout@master @@ -41,9 +57,42 @@ jobs: ~/.cargo/registry ~/.cargo/git target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - restore-keys: ${{ runner.os }}-cargo - - name: Clippy - uses: actions-rs-plus/clippy-check@v2.1.1 - with: - args: --workspace --all-targets --features serde,unix + key: ${{ runner.os }}-cargo-${{ matrix.target }} + - name: Install toolchain + run: rustup target add ${{ matrix.target }} + - name: Check (no features) + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} + cargo doc --workspace --color=always --target ${{ matrix.target }} + - name: Check --features doc + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features doc + cargo doc --workspace --color=always --target ${{ matrix.target }} --features doc + - name: Check --features unix + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features unix + cargo doc --workspace --color=always --target ${{ matrix.target }} --features unix + - name: Check --features windows + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features windows + cargo doc --workspace --color=always --target ${{ matrix.target }} --features windows + - name: Check --features rs4xx + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features rs4xx + cargo doc --workspace --color=always --target ${{ matrix.target }} --features rs4xx + - name: Check --features unix,windows + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features unix,windows + cargo doc --workspace --color=always --target ${{ matrix.target }} --features unix,windows + - name: Check --features unix,rs4xx + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features unix,rs4xx + cargo doc --workspace --color=always --target ${{ matrix.target }} --features unix,rs4xx + - name: Check --features windows,rs4xx + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features windows,rs4xx + cargo doc --workspace --color=always --target ${{ matrix.target }} --features windows,rs4xx + - name: Check --features unix,windows,rs4xx + run: | + cargo clippy --workspace --color=always --target ${{ matrix.target }} --features unix,windows,rs4xx + cargo doc --workspace --color=always --target ${{ matrix.target }} --features unix,windows,rs4xx diff --git a/CHANGELOG b/CHANGELOG index 1c3ef76..d87f764 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +# Unreleased +- [add][minor] Expose the "rs4xx" feature of the `serial2` crate. + # Version 0.1.9 - 2024-01-19 - [change][minor] Update `serial2` to `v0.2.17`. - [fix][minor] Set the `IGNBRK` and `IGNPAR` flags in `Settings::set_raw()` on Unix platforms. diff --git a/Cargo.lock b/Cargo.lock index 7dbac65..531ab25 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "serial2" -version = "0.2.17" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eea9caf87881a41a0d01cc89ee8abc5d690b943b07b282d9cde0a1dbb30cbb6" +checksum = "516706ad5df2cd241b25c206e0360878e721b8c4c93fa7edc20f4bd1d964ccab" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index c392490..670c187 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,15 +18,20 @@ unix = ["serial2/unix"] # The "windows" features enables windows specific extensions. windows = ["serial2/windows"] +# The "rs4xx" feature enables RS-485/RS-422 specific extensions on supported platforms. +rs4xx = ["serial2/rs4xx"] + # Add #[doc(cfg(...))] annotations to platform specific items for better documentation (requires nightly toolchain). doc-cfg = ["serial2/doc-cfg"] +# Enable limited serde support for serial port configuration. serde = ["serial2/serde"] -doc = ["tokio/io-util", "serial2/unix", "serial2/windows"] +# Add stub implementation of all feature and platform specific items, to allow full documentation to build on all platforms. +doc = ["tokio/io-util", "serial2/doc"] [dependencies] -serial2 = "0.2.17" +serial2 = "0.2.24" tokio = { version = "1.32.0", default-features = false, features = ["net"] } [target.'cfg(unix)'.dependencies] @@ -37,6 +42,7 @@ winapi = { version = "0.3.9", features = ["winerror"] } [dev-dependencies] tokio = { version = "1.32.0", features = ["macros", "rt", "io-std", "io-util"] } +serial2 = { version = "0.2.22", features = ["rs4xx"] } [package.metadata.docs.rs] features = ["doc", "doc-cfg"] diff --git a/src/inner/windows.rs b/src/inner/windows.rs index 6cc3883..aae88a0 100644 --- a/src/inner/windows.rs +++ b/src/inner/windows.rs @@ -67,7 +67,7 @@ impl SerialPort { } pub async fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> std::io::Result { - if bufs.len() == 0 { + if bufs.is_empty() { self.read(&mut []).await } else { self.read(&mut bufs[0]).await @@ -95,7 +95,7 @@ impl SerialPort { } pub async fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> std::io::Result { - if bufs.len() == 0 { + if bufs.is_empty() { self.write(&[]).await } else { self.write(&bufs[0]).await diff --git a/src/lib.rs b/src/lib.rs index 3c27832..e369e33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -70,6 +70,11 @@ pub use serial2::{ StopBits, TryFromError, }; + +#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "rs4xx")))] +#[cfg(any(feature = "doc", feature = "rs4xx"))] +pub use serial2::rs4xx; + use tokio::io::{AsyncRead, AsyncWrite}; /// An asynchronous serial port for Tokio. @@ -144,6 +149,7 @@ impl SerialPort { /// /// Note that there are no guarantees about which task receives what data when multiple tasks are reading from the serial port. /// You should normally limit yourself to a single reading task and a single writing task. + #[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))] pub async fn read(&self, buf: &mut [u8]) -> std::io::Result { self.inner.read(buf).await } @@ -171,6 +177,7 @@ impl SerialPort { /// /// Note that data written to the same serial port from multiple tasks may end up interleaved at the receiving side. /// You should normally limit yourself to a single reading task and a single writing task. + #[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))] pub async fn write(&self, buf: &[u8]) -> std::io::Result { self.inner.write(buf).await } @@ -185,6 +192,7 @@ impl SerialPort { /// /// Note that data written to the same serial port from multiple tasks may end up interleaved at the receiving side. /// You should normally limit yourself to a single reading task and a single writing task. + #[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))] pub async fn write_all(&self, buf: &[u8]) -> std::io::Result<()> { let mut written = 0; while written < buf.len() { @@ -200,6 +208,7 @@ impl SerialPort { /// /// Note that data written to the same serial port from multiple tasks may end up interleaved at the receiving side. /// You should normally limit yourself to a single reading task and a single writing task. + #[cfg_attr(not(feature = "doc"), allow(rustdoc::broken_intra_doc_links))] pub async fn write_vectored(&self, buf: &[IoSlice<'_>]) -> std::io::Result { self.inner.write_vectored(buf).await } @@ -287,6 +296,42 @@ impl SerialPort { pub fn read_cd(&self) -> std::io::Result { self.inner.with_raw(|raw| raw.read_cd()) } + + /// Get the RS-4xx mode of the serial port transceiver. + /// + /// This is currently only supported on Linux. + /// + /// Not all serial ports can be configured in a different mode by software. + /// Some serial ports are always in RS-485 or RS-422 mode, + /// and some may have hardware switches or jumpers to configure the transceiver. + /// In those cases, this function will usually report an error or [`rs4xx::TransceiverMode::Default`], + /// even though the serial port is configured is RS-485 or RS-422 mode. + /// + /// Note that driver support for this feature is very limited and sometimes inconsistent. + /// Please read all the warnings in the [`rs4xx`] module carefully. + #[cfg(any(feature = "doc", all(feature = "rs4xx", target_os = "linux")))] + #[cfg_attr(feature = "doc-cfg", doc(cfg(all(feature = "rs4xx", target_os = "linux"))))] + pub fn get_rs4xx_mode(&self) -> std::io::Result { + self.inner.with_raw(|raw| raw.get_rs4xx_mode()) + } + + /// Set the RS-4xx mode of the serial port transceiver. + /// + /// This is currently only supported on Linux. + /// + /// Not all serial ports can be configured in a different mode by software. + /// Some serial ports are always in RS-485 or RS-422 mode, + /// and some may have hardware switches or jumpers to configure the transceiver. + /// In that case, this function will usually return an error, + /// but the port can still be in RS-485 or RS-422 mode. + /// + /// Note that driver support for this feature is very limited and sometimes inconsistent. + /// Please read all the warnings in the [`rs4xx`] module carefully. + #[cfg(any(feature = "doc", all(feature = "rs4xx", target_os = "linux")))] + #[cfg_attr(feature = "doc-cfg", doc(cfg(all(feature = "rs4xx", target_os = "linux"))))] + pub fn set_rs4xx_mode(&self, mode: impl Into) -> std::io::Result<()> { + self.inner.with_raw(|raw| raw.set_rs4xx_mode(mode)) + } } impl AsyncRead for SerialPort {