use crate::error::{M17Error, SoundmodemError};
use crate::tnc::{Tnc, TncError};
+use crate::util::out_buffer::OutBuffer;
use m17core::kiss::MAX_FRAME_LEN;
use m17core::modem::{Demodulator, Modulator, ModulatorAction, SoftDemodulator, SoftModulator};
use m17core::tnc::SoftTnc;
use std::collections::VecDeque;
use std::fmt::Display;
use std::fs::File;
-use std::io::{self, ErrorKind, Read, Write};
+use std::io::{self, Read, Write};
use std::path::PathBuf;
use std::sync::mpsc::{channel, sync_channel, Receiver, Sender, SyncSender, TryRecvError};
use std::sync::RwLock;
pub struct Soundmodem {
event_tx: SyncSender<SoundmodemEvent>,
- kiss_out_rx: Arc<Mutex<Receiver<Arc<[u8]>>>>,
- partial_kiss_out: Arc<Mutex<Option<PartialKissOut>>>,
+ kiss_out: OutBuffer,
}
impl Soundmodem {
);
Self {
event_tx,
- kiss_out_rx: Arc::new(Mutex::new(kiss_out_rx)),
- partial_kiss_out: Arc::new(Mutex::new(None)),
+ kiss_out: OutBuffer::new(kiss_out_rx),
}
}
}
}
}
-struct PartialKissOut {
- output: Arc<[u8]>,
- idx: usize,
-}
-
impl Read for Soundmodem {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- {
- let mut partial_kiss_out = self.partial_kiss_out.lock().unwrap();
- if let Some(partial) = partial_kiss_out.as_mut() {
- let remaining = partial.output.len() - partial.idx;
- let to_write = remaining.min(buf.len());
- buf[0..to_write]
- .copy_from_slice(&partial.output[partial.idx..(partial.idx + to_write)]);
- if to_write == remaining {
- *partial_kiss_out = None;
- } else {
- partial.idx += to_write;
- }
- return Ok(to_write);
- }
- }
- let output = {
- let rx = self.kiss_out_rx.lock().unwrap();
- rx.recv()
- .map_err(|s| io::Error::new(ErrorKind::Other, format!("{:?}", s)))?
- };
- let to_write = output.len().min(buf.len());
- buf[0..to_write].copy_from_slice(&output[0..to_write]);
- if to_write != output.len() {
- *self.partial_kiss_out.lock().unwrap() = Some(PartialKissOut {
- output,
- idx: to_write,
- })
- }
- Ok(to_write)
+ self.kiss_out.read(buf)
}
}
fn try_clone(&mut self) -> Result<Self, TncError> {
Ok(Self {
event_tx: self.event_tx.clone(),
- kiss_out_rx: self.kiss_out_rx.clone(),
- partial_kiss_out: self.partial_kiss_out.clone(),
+ kiss_out: self.kiss_out.clone(),
})
}
--- /dev/null
+//! Buffer between `read()` calls
+
+use std::{
+ io::{self, ErrorKind, Read},
+ sync::{mpsc::Receiver, Arc, Mutex},
+};
+
+#[derive(Clone)]
+struct PartialOut {
+ output: Arc<[u8]>,
+ idx: usize,
+}
+
+/// Buffer binary chunks from an MPSC receiver, feeding arbitrary chunks to `read()` calls.
+///
+/// Can be cloned, but should only be read from once at a time.
+#[derive(Clone)]
+pub struct OutBuffer {
+ rx: Arc<Mutex<Receiver<Arc<[u8]>>>>,
+ partial_out: Arc<Mutex<Option<PartialOut>>>,
+}
+
+impl OutBuffer {
+ pub fn new(rx: Receiver<Arc<[u8]>>) -> Self {
+ Self {
+ rx: Arc::new(Mutex::new(rx)),
+ partial_out: Arc::new(Mutex::new(None)),
+ }
+ }
+}
+
+impl Read for OutBuffer {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ {
+ let mut partial_out = self.partial_out.lock().unwrap();
+ if let Some(partial) = partial_out.as_mut() {
+ let remaining = partial.output.len() - partial.idx;
+ let to_write = remaining.min(buf.len());
+ buf[0..to_write]
+ .copy_from_slice(&partial.output[partial.idx..(partial.idx + to_write)]);
+ if to_write == remaining {
+ *partial_out = None;
+ } else {
+ partial.idx += to_write;
+ }
+ return Ok(to_write);
+ }
+ }
+ let output = {
+ let rx = self.rx.lock().unwrap();
+ rx.recv()
+ .map_err(|s| io::Error::new(ErrorKind::Other, format!("{:?}", s)))?
+ };
+ let to_write = output.len().min(buf.len());
+ buf[0..to_write].copy_from_slice(&output[0..to_write]);
+ if to_write != output.len() {
+ *self.partial_out.lock().unwrap() = Some(PartialOut {
+ output,
+ idx: to_write,
+ })
+ }
+ Ok(to_write)
+ }
+}