mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-04 23:26:41 +00:00
Adhere to RAII
This commit is contained in:
parent
1eddc2e3a2
commit
edb429ed43
@ -264,7 +264,7 @@ fn main() -> Result<(), Error> {
|
||||
let converter = ConverterImpl::new(char_converter, color_converter);
|
||||
let term = TerminalImpl::new(stdout());
|
||||
let printer = PrinterImpl::new(term)?;
|
||||
let renderer = RendererImpl::new(sampler, converter, printer);
|
||||
let renderer = RendererImpl::new(sampler, converter, printer)?;
|
||||
|
||||
let clock = ClockImpl::new();
|
||||
let timer = Timer::new(clock, duration, delay);
|
||||
|
119
src/renderer.rs
119
src/renderer.rs
@ -3,33 +3,35 @@ use crate::pattern::*;
|
||||
use crate::Error;
|
||||
use crate::Printer;
|
||||
use crate::Vector;
|
||||
use crossterm::style::Color;
|
||||
|
||||
/// A renderer for an animation.
|
||||
#[cfg_attr(test, mockall::automock)]
|
||||
pub trait Renderer {
|
||||
/// Prepares the terminal for the animation.
|
||||
/// Call once before rendering frames.
|
||||
fn begin(&mut self) -> Result<(), Error>;
|
||||
/// Renders the current frame and flushes.
|
||||
fn render(&mut self, step: f32) -> Result<(), Error>;
|
||||
/// Cleans up and resets the terminal.
|
||||
/// Call once after rendering frames.
|
||||
fn end(&mut self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// The implementation of [Renderer].
|
||||
#[derive(derive_more::Constructor)]
|
||||
pub struct RendererImpl<T1, T2, T3> {
|
||||
pub struct RendererImpl<T1, T2, T3: Printer> {
|
||||
sampler: T1,
|
||||
converter: T2,
|
||||
printer: T3,
|
||||
}
|
||||
|
||||
impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T1, T2, T3> {
|
||||
fn begin(&mut self) -> Result<(), Error> {
|
||||
self.printer.hide_cursor()
|
||||
impl<T1, T2, T3: Printer> RendererImpl<T1, T2, T3> {
|
||||
pub fn new(sampler: T1, converter: T2, mut printer: T3) -> Result<Self, Error> {
|
||||
printer.hide_cursor()?;
|
||||
|
||||
Ok(Self {
|
||||
sampler,
|
||||
converter,
|
||||
printer,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T1, T2, T3> {
|
||||
fn render(&mut self, step: f32) -> Result<(), Error> {
|
||||
let (width, height) = self.printer.size()?;
|
||||
let config = Config {
|
||||
@ -60,12 +62,16 @@ impl<T1: SamplerFactory, T2: Converter, T3: Printer> Renderer for RendererImpl<T
|
||||
}
|
||||
self.printer.flush()
|
||||
}
|
||||
}
|
||||
|
||||
fn end(&mut self) -> Result<(), Error> {
|
||||
self.printer.move_to(0, 0)?;
|
||||
self.printer.clear()?;
|
||||
self.printer.show_cursor()?;
|
||||
self.printer.flush()
|
||||
impl<T1, T2, T3: Printer> Drop for RendererImpl<T1, T2, T3> {
|
||||
fn drop(&mut self) {
|
||||
// Errors while dropping the renderer can be safely ignored.
|
||||
self.printer.move_to(0, 0).ok();
|
||||
self.printer.set_foreground(Color::Reset).ok();
|
||||
self.printer.show_cursor().ok();
|
||||
self.printer.clear().ok();
|
||||
self.printer.flush().ok();
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,16 +87,22 @@ mod test {
|
||||
use mockall::Sequence;
|
||||
|
||||
#[test]
|
||||
fn begin() {
|
||||
fn new() {
|
||||
let factory = MockSamplerFactory::new();
|
||||
let converter = MockConverter::new();
|
||||
let mut printer = MockPrinter::new();
|
||||
|
||||
// Constructor
|
||||
printer.expect_hide_cursor().once().returning(|| Ok(()));
|
||||
|
||||
let mut renderer = RendererImpl::new(factory, converter, printer);
|
||||
// Drop
|
||||
printer.expect_move_to().returning(|_, _| Ok(()));
|
||||
printer.expect_set_foreground().returning(|_| Ok(()));
|
||||
printer.expect_show_cursor().returning(|| Ok(()));
|
||||
printer.expect_clear().returning(|| Ok(()));
|
||||
printer.expect_flush().returning(|| Ok(()));
|
||||
|
||||
renderer.begin().unwrap();
|
||||
drop(RendererImpl::new(factory, converter, printer));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -163,6 +175,14 @@ mod test {
|
||||
|
||||
let seq = &mut Sequence::new();
|
||||
|
||||
// Constructor
|
||||
printer
|
||||
.expect_hide_cursor()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
|
||||
// Rendering
|
||||
printer
|
||||
.expect_move_to()
|
||||
.once()
|
||||
@ -217,7 +237,35 @@ mod test {
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
|
||||
let mut renderer = RendererImpl::new(sampler, converter, printer);
|
||||
// Drop
|
||||
printer
|
||||
.expect_move_to()
|
||||
.once()
|
||||
.returning(|_, _| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_set_foreground()
|
||||
.with(eq(Color::Reset))
|
||||
.once()
|
||||
.returning(|_| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_show_cursor()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_clear()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_flush()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
|
||||
let mut renderer = RendererImpl::new(sampler, converter, printer).unwrap();
|
||||
|
||||
renderer.render(0.0).unwrap();
|
||||
}
|
||||
@ -237,7 +285,17 @@ mod test {
|
||||
printer.expect_size().returning(|| Ok((3, 2)));
|
||||
printer.expect_flush().returning(|| Ok(()));
|
||||
|
||||
let mut renderer = RendererImpl::new(sampler, converter, printer);
|
||||
// Constructor
|
||||
printer.expect_hide_cursor().returning(|| Ok(()));
|
||||
|
||||
// Drop
|
||||
printer.expect_move_to().returning(|_, _| Ok(()));
|
||||
printer.expect_set_foreground().returning(|_| Ok(()));
|
||||
printer.expect_show_cursor().returning(|| Ok(()));
|
||||
printer.expect_clear().returning(|| Ok(()));
|
||||
printer.expect_flush().returning(|| Ok(()));
|
||||
|
||||
let mut renderer = RendererImpl::new(sampler, converter, printer).unwrap();
|
||||
|
||||
renderer.render(0.8).unwrap();
|
||||
}
|
||||
@ -249,6 +307,11 @@ mod test {
|
||||
let mut printer = MockPrinter::new();
|
||||
|
||||
let seq = &mut Sequence::new();
|
||||
|
||||
// Constructor
|
||||
printer.expect_hide_cursor().returning(|| Ok(()));
|
||||
|
||||
// Drop
|
||||
printer
|
||||
.expect_move_to()
|
||||
.with(eq(0), eq(0))
|
||||
@ -256,12 +319,18 @@ mod test {
|
||||
.returning(|_, _| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_clear()
|
||||
.expect_set_foreground()
|
||||
.with(eq(Color::Reset))
|
||||
.once()
|
||||
.returning(|_| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_show_cursor()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
printer
|
||||
.expect_show_cursor()
|
||||
.expect_clear()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
@ -271,8 +340,6 @@ mod test {
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(seq);
|
||||
|
||||
let mut renderer = RendererImpl::new(factory, converter, printer);
|
||||
|
||||
renderer.end().unwrap();
|
||||
drop(RendererImpl::new(factory, converter, printer));
|
||||
}
|
||||
}
|
||||
|
18
src/timer.rs
18
src/timer.rs
@ -41,15 +41,13 @@ impl<T: Clock> Timer<T> {
|
||||
let start = self.clock.now();
|
||||
let mut now = start;
|
||||
|
||||
renderer.begin()?;
|
||||
|
||||
while now.duration_since(start) < self.duration {
|
||||
let step = now.duration_since(start).as_secs_f32() / self.duration.as_secs_f32();
|
||||
|
||||
renderer.render(step)?;
|
||||
now = self.delay(now);
|
||||
}
|
||||
renderer.end()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sleeps until the next frame starts.
|
||||
@ -98,11 +96,6 @@ mod test {
|
||||
let mut renderer = MockRenderer::new();
|
||||
let renderer_seq = &mut Sequence::new();
|
||||
|
||||
renderer
|
||||
.expect_begin()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(renderer_seq);
|
||||
renderer
|
||||
.expect_render()
|
||||
.with(eq(0.0))
|
||||
@ -115,11 +108,6 @@ mod test {
|
||||
.once()
|
||||
.returning(|_| Ok(()))
|
||||
.in_sequence(renderer_seq);
|
||||
renderer
|
||||
.expect_end()
|
||||
.once()
|
||||
.returning(|| Ok(()))
|
||||
.in_sequence(renderer_seq);
|
||||
|
||||
timer.run(renderer).unwrap();
|
||||
}
|
||||
@ -155,9 +143,7 @@ mod test {
|
||||
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
||||
|
||||
let mut renderer = MockRenderer::new();
|
||||
renderer.expect_begin().returning(|| Ok(()));
|
||||
renderer.expect_render().returning(|_| Ok(()));
|
||||
renderer.expect_end().returning(|| Ok(()));
|
||||
|
||||
timer.run(renderer).unwrap();
|
||||
}
|
||||
@ -182,9 +168,7 @@ mod test {
|
||||
let timer = Timer::new(clock, Duration::from_secs(10), Duration::from_secs(10));
|
||||
|
||||
let mut renderer = MockRenderer::new();
|
||||
renderer.expect_begin().returning(|| Ok(()));
|
||||
renderer.expect_render().returning(|_| Ok(()));
|
||||
renderer.expect_end().returning(|| Ok(()));
|
||||
|
||||
timer.run(renderer).unwrap();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user