1use crate::sys;
4use core::{
5 fmt::{self, Write},
6 mem,
7};
8
9const BUF_SIZE: usize = 16;
12
13#[derive(Debug, Clone, Copy)]
15pub struct Writer(
16 pub sys::FileDesc,
18);
19
20impl Writer {
21 pub fn write_fmt(
23 &self,
24 arguments: fmt::Arguments,
25 ) -> Result<(), sys::Error> {
26 let mut adapter = Adapter::new(self.0);
27 let _ = adapter.write_fmt(arguments);
28 adapter.finish()
29 }
30}
31
32#[derive(Debug)]
36struct Adapter {
37 desc: sys::FileDesc,
39 buffer: [u8; BUF_SIZE],
41 cursor: usize,
43 result: Result<(), sys::Error>,
45}
46
47impl Adapter {
48 fn new(desc: sys::FileDesc) -> Self {
50 Self { desc, buffer: [0; BUF_SIZE], cursor: 0, result: Ok(()) }
51 }
52
53 fn flush(&mut self) -> Result<(), sys::Error> {
55 sys::write(self.desc, &self.buffer[.. self.cursor])?;
56 self.buffer = [0; BUF_SIZE];
57 self.cursor = 0;
58 Ok(())
59 }
60
61 fn finish(mut self) -> Result<(), sys::Error> {
63 mem::replace(&mut self.result, Ok(()))
64 }
65}
66
67impl Write for Adapter {
68 fn write_str(&mut self, data: &str) -> fmt::Result {
69 let mut bytes = data.as_bytes();
70
71 while bytes.len() > 0 && self.result.is_ok() {
72 let start = self.cursor;
73 let size = (BUF_SIZE - self.cursor).min(bytes.len());
74 let end = start + size;
75
76 self.buffer[start .. end].copy_from_slice(&bytes[.. size]);
77 self.cursor = end;
78 bytes = &bytes[size ..];
79
80 if bytes.len() > 0 {
81 self.result = self.flush();
82 }
83 }
84
85 match self.result {
86 Ok(_) => Ok(()),
87 Err(_) => Err(fmt::Error),
88 }
89 }
90}
91
92impl Drop for Adapter {
93 fn drop(&mut self) {
94 let _ = self.flush();
95 let _ = sys::fsync(self.desc);
96 }
97}