rw_builder/
string.rs

1use std::{
2    fmt::{Display, Error},
3    io::{Read, Write},
4};
5
6use anyhow::Result;
7
8use 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)]
14pub struct Builder<B>
15where
16    B: RwBuilder,
17{
18    /// The inner builder it wraps
19    builder: B,
20}
21
22impl<B> Builder<B>
23where
24    B: RwBuilder,
25{
26    /// Factory function to wrap an inner builder
27    #[must_use]
28    pub const fn new(builder: B) -> Self {
29        Self { builder }
30    }
31}
32
33impl<B> Display for Builder<B>
34where
35    B: RwBuilder,
36{
37    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        let mut reader = self.builder.reader().or(Err(Error))?;
41        let mut buffer = vec![0u8; BLOCK_SIZE];
42        let mut position: usize = 0;
43        while let Ok(bytes) = reader.read(&mut buffer[position..]) {
44            if bytes == BLOCK_SIZE {
45                position += BLOCK_SIZE;
46                buffer.extend_from_slice(&[0u8; BLOCK_SIZE]);
47            } else {
48                buffer.truncate(position + bytes);
49                break;
50            }
51        }
52        write!(f, "{}", String::from_utf8(buffer).or(Err(Error))?)
53    }
54}
55
56/// Creates a writer and writes the string to it
57pub 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
65impl<B> AdhocWriter for Builder<B>
66where
67    B: RwBuilder,
68{
69    fn write_string(&self, text: &str) -> Result<()> {
70        let mut writer = self.builder.writer()?;
71        let byte_count = writer.write(text.as_bytes())?;
72        assert_eq!(byte_count, text.len());
73        Ok(writer.flush()?)
74    }
75}