use crate::Result;
use crate::protocol::ErrorCode;
use crate::serial::V4Serial;
use indicatif::{ProgressBar, ProgressStyle};
use std::fs;
use std::path::Path;
use std::time::Duration;
pub fn push(file: &str, port: &str, detach: bool, timeout: Duration) -> Result<()> {
let path = Path::new(file);
if !path.exists() {
return Err(crate::V4Error::Io(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("Bytecode file not found: {}", file),
)));
}
let bytecode = fs::read(path)?;
let size = bytecode.len();
println!("Loading bytecode from {} ({} bytes)...", file, size);
if size == 0 {
return Err(crate::V4Error::Protocol(
"Bytecode file is empty".to_string(),
));
}
let pb = ProgressBar::new(size as u64);
pb.set_style(
ProgressStyle::default_bar()
.template("[{elapsed_precise}] {bar:40.cyan/blue} {bytes}/{total_bytes} {msg}")
.unwrap()
.progress_chars("=>-"),
);
let mut serial = V4Serial::open_default(port)?;
pb.set_message("Sending...");
let response = serial.exec(&bytecode, timeout)?;
pb.inc(size as u64);
if detach {
pb.finish_with_message("Sent (detached)");
println!("Bytecode sent to device (not waiting for response)");
return Ok(());
}
pb.finish_with_message("Complete");
println!("Response: {}", response.error_code.name());
if response.error_code == ErrorCode::Ok {
println!("✓ Bytecode deployed successfully");
if !response.word_indices.is_empty() {
println!(" Registered {} word(s)", response.word_indices.len());
}
Ok(())
} else {
Err(crate::V4Error::Device(format!(
"Device returned error: {}",
response.error_code.name()
)))
}
}