blob: ad7cec40da7e2fa53ce74c22bd3fc11731758ad3 [file]
// Licensed under the Apache-2.0 license
//! I2C transaction operation types.
//!
//! This module provides the `Operation` enum for building
//! multi-operation I2C transactions.
use core::fmt;
/// An I2C operation within a transaction.
///
/// Used with [`I2cClient::transaction`] to execute multiple operations
/// without releasing the bus between them.
///
/// # Examples
///
/// ```rust,ignore
/// use i2c_api::{I2cClient, Operation, BusIndex, I2cAddress};
///
/// // Write register address, then read 4 bytes
/// let mut read_buf = [0u8; 4];
/// client.transaction(bus, address, &mut [
/// Operation::Write(&[0x00]), // Register address
/// Operation::Read(&mut read_buf), // Read response
/// ])?;
/// ```
#[derive(Debug)]
pub enum Operation<'a> {
/// Write data to the device.
///
/// The slice contains bytes to send. An empty slice can be used
/// for address-only probing.
Write(&'a [u8]),
/// Read data from the device.
///
/// The slice is filled with received bytes. The length determines
/// how many bytes to read.
Read(&'a mut [u8]),
}
impl<'a> Operation<'a> {
/// Returns `true` if this is a write operation.
#[inline]
pub const fn is_write(&self) -> bool {
matches!(self, Operation::Write(_))
}
/// Returns `true` if this is a read operation.
#[inline]
pub const fn is_read(&self) -> bool {
matches!(self, Operation::Read(_))
}
/// Returns the length of data involved in this operation.
pub fn len(&self) -> usize {
match self {
Operation::Write(data) => data.len(),
Operation::Read(data) => data.len(),
}
}
/// Returns `true` if this operation has no data.
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl fmt::Display for Operation<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Operation::Write(data) => write!(f, "Write({} bytes)", data.len()),
Operation::Read(data) => write!(f, "Read({} bytes)", data.len()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_operation_is_write() {
let op = Operation::Write(&[0x00, 0x01]);
assert!(op.is_write());
assert!(!op.is_read());
}
#[test]
fn test_operation_is_read() {
let mut buf = [0u8; 4];
let op = Operation::Read(&mut buf);
assert!(op.is_read());
assert!(!op.is_write());
}
#[test]
fn test_operation_len() {
let write_op = Operation::Write(&[0x00, 0x01, 0x02]);
assert_eq!(write_op.len(), 3);
let mut buf = [0u8; 8];
let read_op = Operation::Read(&mut buf);
assert_eq!(read_op.len(), 8);
}
#[test]
fn test_operation_empty() {
let empty_write = Operation::Write(&[]);
assert!(empty_write.is_empty());
let mut empty_buf: [u8; 0] = [];
let empty_read = Operation::Read(&mut empty_buf);
assert!(empty_read.is_empty());
}
}