1
use std::{
2
    fmt::{Display, Error},
3
    io::{Read, Write},
4
};
5

            
6
use anyhow::Result;
7

            
8
use crate::RwBuilder;
9

            
10
/// Type returned by the `string` function on the `RwBuilder` trait.
11
/// It is itself not an `RwBuilder` so can't be chained further.
12
/// This is why we call it a sink.
13
#[derive(Debug)]
14
pub struct Builder<B>
15
where
16
    B: RwBuilder,
17
{
18
    /// The inner builder it wraps
19
    builder: B,
20
}
21

            
22
impl<B> Builder<B>
23
where
24
    B: RwBuilder,
25
{
26
    /// Factory function to wrap an inner builder
27
    #[must_use]
28
8
    pub const fn new(builder: B) -> Self {
29
8
        Self { builder }
30
8
    }
31
}
32

            
33
impl<B> Display for Builder<B>
34
where
35
    B: RwBuilder,
36
{
37
8
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38
        /// The size with which the buffer is extended until the reader is empty
39
        const BLOCK_SIZE: usize = 1024;
40
8
        let mut reader = self.builder.reader().or(Err(Error))?;
41
8
        let mut buffer = vec![0u8; BLOCK_SIZE];
42
8
        let mut position: usize = 0;
43
11
        while let Ok(bytes) = reader.read(&mut buffer[position..]) {
44
11
            if bytes == BLOCK_SIZE {
45
3
                position += BLOCK_SIZE;
46
3
                buffer.extend_from_slice(&[0u8; BLOCK_SIZE]);
47
3
            } else {
48
8
                buffer.truncate(position + bytes);
49
8
                break;
50
            }
51
        }
52
8
        write!(f, "{}", String::from_utf8(buffer).or(Err(Error))?)
53
8
    }
54
}
55

            
56
/// Creates a writer and writes the string to it
57
pub trait AdhocWriter {
58
    /// Write a string to a built writer
59
    /// # Errors
60
    /// If either the writer creation or the write operation fails the error is
61
    /// propagated.
62
    fn write_string(&self, text: &str) -> Result<()>;
63
}
64

            
65
impl<B> AdhocWriter for Builder<B>
66
where
67
    B: RwBuilder,
68
{
69
7
    fn write_string(&self, text: &str) -> Result<()> {
70
7
        let mut writer = self.builder.writer()?;
71
7
        let byte_count = writer.write(text.as_bytes())?;
72
7
        assert_eq!(byte_count, text.len());
73
7
        Ok(writer.flush()?)
74
7
    }
75
}