Skip to content

Commit 7296434

Browse files
00xcJonathanWoollett-Light
authored andcommitted
serial: add methods to retrieve the underlying output writer
Add three methods (writer(), writer_mut() and into_writer()) to Serial in order to obtain the original output object back from the device. This allows the device to gain ownership of the object and for the caller to retrieve it back when needed. Otherwise, if one wants the device to write output into an in-memory structure (e.g. a Vec), which can later be accessed, one must give out a mutable reference. This can be problematic if one stores the buffer and the device within the same structure due to Rust's issues with self-referential structures. This is also more ergonomic in terms of saving and restoring the device's state, if one considers the output part of the state. Signed-off-by: Carlos López <[email protected]>
1 parent 75b378f commit 7296434

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

vm-superio/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- Added a `reset_evt` to the `I8042Device` type to retrieve the underlying
88
reset event object.
9+
- Added three methods to `Serial` to retrieve the `Write` output object.
910

1011
# v0.7.0
1112

vm-superio/src/serial.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,79 @@ impl<T: Trigger, EV: SerialEvents, W: Write> Serial<T, EV, W> {
401401
}
402402
}
403403

404+
/// Gets a reference to the output Write object
405+
///
406+
/// ```rust
407+
/// # use vm_superio::Trigger;
408+
/// # use vm_superio::serial::Serial;
409+
/// # struct DummyTrigger;
410+
/// # impl Trigger for DummyTrigger {
411+
/// # type E = ();
412+
/// # fn trigger(&self) -> Result<(), ()> { Ok(()) }
413+
/// # }
414+
/// const DATA_OFFSET: u8 = 0;
415+
///
416+
/// let output = Vec::new();
417+
/// let mut serial = Serial::new(DummyTrigger, output);
418+
/// serial.write(DATA_OFFSET, 0x66).unwrap();
419+
/// assert_eq!(serial.writer().first().copied(), Some(0x66));
420+
/// ```
421+
pub fn writer(&self) -> &W {
422+
&self.out
423+
}
424+
425+
/// Gets a mutable reference to the output Write object
426+
///
427+
/// ```rust
428+
/// # use vm_superio::Trigger;
429+
/// # use vm_superio::serial::Serial;
430+
/// # struct DummyTrigger;
431+
/// # impl Trigger for DummyTrigger {
432+
/// # type E = ();
433+
/// # fn trigger(&self) -> Result<(), ()> { Ok(()) }
434+
/// # }
435+
/// const DATA_OFFSET: u8 = 0;
436+
///
437+
/// let output = Vec::new();
438+
/// let mut serial = Serial::new(DummyTrigger, output);
439+
/// serial.write(DATA_OFFSET, 0x66).unwrap();
440+
/// serial.writer_mut().clear();
441+
/// assert_eq!(serial.writer().first(), None);
442+
/// ```
443+
pub fn writer_mut(&mut self) -> &mut W {
444+
&mut self.out
445+
}
446+
447+
/// Consumes the device and retrieves the inner writer. This
448+
/// can be useful when restoring a copy of the device.
449+
///
450+
/// ```rust
451+
/// # use vm_superio::Trigger;
452+
/// # use vm_superio::serial::{NoEvents, Serial};
453+
/// # struct DummyTrigger;
454+
/// # impl Trigger for DummyTrigger {
455+
/// # type E = ();
456+
/// # fn trigger(&self) -> Result<(), ()> { Ok(()) }
457+
/// # }
458+
/// const DATA_OFFSET: u8 = 0;
459+
///
460+
/// // Create a device with some state
461+
/// let output = Vec::new();
462+
/// let mut serial = Serial::new(DummyTrigger, output);
463+
/// serial.write(DATA_OFFSET, 0x66).unwrap();
464+
///
465+
/// // Save the state
466+
/// let state = serial.state();
467+
/// let output = serial.into_writer();
468+
///
469+
/// // Restore the device
470+
/// let restored_serial = Serial::from_state(&state, DummyTrigger, NoEvents, output).unwrap();
471+
/// assert_eq!(restored_serial.writer().first().copied(), Some(0x66));
472+
/// ```
473+
pub fn into_writer(self) -> W {
474+
self.out
475+
}
476+
404477
/// Provides a reference to the interrupt event object.
405478
pub fn interrupt_evt(&self) -> &T {
406479
&self.interrupt_evt

0 commit comments

Comments
 (0)