Skip to main content

qubit_text_io/adapters/
utf8_text_writer.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::io::{
11    self,
12    Write,
13};
14
15use crate::{
16    LineEnding,
17    TextWrite,
18};
19
20/// Text writer that encodes text as UTF-8 bytes.
21#[derive(Debug)]
22pub struct Utf8TextWriter<W> {
23    inner: W,
24    line_ending: LineEnding,
25}
26
27impl<W> Utf8TextWriter<W>
28where
29    W: Write,
30{
31    /// Creates a UTF-8 text writer.
32    ///
33    /// # Parameters
34    /// - `inner`: Byte writer to receive UTF-8 bytes.
35    ///
36    /// # Returns
37    /// A text writer using LF line endings.
38    #[must_use]
39    pub const fn new(inner: W) -> Self {
40        Self {
41            inner,
42            line_ending: LineEnding::Lf,
43        }
44    }
45
46    /// Sets the line ending for this writer.
47    ///
48    /// # Parameters
49    /// - `line_ending`: Line ending to use for subsequent lines.
50    ///
51    /// # Returns
52    /// This writer with the configured line ending.
53    #[must_use]
54    pub const fn with_line_ending(mut self, line_ending: LineEnding) -> Self {
55        self.line_ending = line_ending;
56        self
57    }
58
59    /// Returns a shared reference to the wrapped byte writer.
60    ///
61    /// # Returns
62    /// The wrapped byte writer.
63    #[must_use]
64    pub const fn get_ref(&self) -> &W {
65        &self.inner
66    }
67
68    /// Returns a mutable reference to the wrapped byte writer.
69    ///
70    /// # Returns
71    /// The wrapped byte writer.
72    pub fn get_mut(&mut self) -> &mut W {
73        &mut self.inner
74    }
75
76    /// Returns the wrapped byte writer.
77    ///
78    /// # Returns
79    /// The underlying byte writer.
80    #[must_use]
81    pub fn into_inner(self) -> W {
82        self.inner
83    }
84}
85
86impl<W> TextWrite for Utf8TextWriter<W>
87where
88    W: Write,
89{
90    type Error = io::Error;
91
92    #[inline]
93    fn line_ending(&self) -> LineEnding {
94        self.line_ending
95    }
96
97    #[inline]
98    fn write_char(&mut self, ch: char) -> Result<(), Self::Error> {
99        let mut buffer = [0_u8; 4];
100        self.write_str(ch.encode_utf8(&mut buffer))
101    }
102
103    fn write_chars(&mut self, chars: &[char]) -> Result<(), Self::Error> {
104        for ch in chars {
105            self.write_char(*ch)?;
106        }
107        Ok(())
108    }
109
110    #[inline]
111    fn write_str(&mut self, text: &str) -> Result<(), Self::Error> {
112        self.inner.write_all(text.as_bytes())
113    }
114
115    fn write_line(&mut self, line: &str) -> Result<(), Self::Error> {
116        self.write_str(line)?;
117        self.write_str(self.line_ending.as_str())
118    }
119
120    #[inline]
121    fn flush(&mut self) -> Result<(), Self::Error> {
122        self.inner.flush()
123    }
124}