#![warn(missing_docs)]
#![warn(clippy::all)]
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
pub mod device;
pub mod error;
pub mod host;
pub mod image;
pub mod monitor;
pub mod port;
pub mod protocol;
pub mod target;
static INTERRUPT_FLAG: AtomicBool = AtomicBool::new(false);
#[derive(Clone, Default)]
pub struct CancelContext {
checker: Option<Arc<dyn Fn() -> bool + Send + Sync>>,
}
impl CancelContext {
#[must_use]
pub fn new<F>(checker: F) -> Self
where
F: Fn() -> bool + Send + Sync + 'static,
{
Self {
checker: Some(Arc::new(checker)),
}
}
#[must_use]
pub fn none() -> Self {
Self { checker: None }
}
#[must_use]
pub fn is_cancelled(&self) -> bool {
self.checker
.as_ref()
.is_some_and(|c| c())
}
pub fn check(&self) -> crate::Result<()> {
if self.is_cancelled() {
return Err(crate::Error::Io(std::io::Error::new(
std::io::ErrorKind::Interrupted,
"operation cancelled",
)));
}
Ok(())
}
}
impl From<fn() -> bool> for CancelContext {
fn from(checker: fn() -> bool) -> Self {
Self::new(checker)
}
}
#[must_use]
pub fn cancel_context_from_global() -> CancelContext {
CancelContext::new(|| INTERRUPT_FLAG.load(Ordering::SeqCst))
}
pub fn set_interrupt_flag() {
INTERRUPT_FLAG.store(true, Ordering::SeqCst);
}
pub fn clear_interrupt_flag() {
INTERRUPT_FLAG.store(false, Ordering::SeqCst);
}
#[must_use]
pub fn is_interrupted_requested() -> bool {
INTERRUPT_FLAG.load(Ordering::SeqCst)
}
#[cfg(test)]
pub(crate) fn test_set_interrupted(value: bool) {
INTERRUPT_FLAG.store(value, Ordering::SeqCst);
}
#[cfg(feature = "native")]
pub use port::{NativePort, NativePortEnumerator};
pub use target::{ChipConfig, ChipFamily, ChipOps, Flasher};
pub use {
device::{DetectedPort, DeviceKind, TransportKind, UsbDevice},
error::{Error, Result},
host::{auto_detect_port, discover_hisilicon_ports, discover_ports},
image::fwpkg::{Fwpkg, FwpkgBinInfo, FwpkgHeader, FwpkgVersion, PartitionType},
monitor::{
MonitorSession, clean_monitor_text, drain_utf8_lossy, format_monitor_output, split_utf8,
},
port::{Port, PortEnumerator, PortInfo, SerialConfig},
protocol::seboot::{CommandType, ImageType, SebootAck, SebootFrame, contains_handshake_ack},
};
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_interrupt_checker_default_false() {
test_set_interrupted(false);
assert!(!is_interrupted_requested());
}
#[test]
fn test_interrupt_checker_toggle_true_false() {
test_set_interrupted(true);
assert!(is_interrupted_requested());
test_set_interrupted(false);
assert!(!is_interrupted_requested());
}
}