libyaml/
emitter.rs

1use std::io;
2use std::mem;
3use std::os::raw;
4use std::slice;
5
6use crate::{EmitterError, Event};
7use crate::sys;
8
9/// Emitter.
10pub struct Emitter<'a> {
11    inner: sys::yaml_emitter_t,
12    writer: Box<dyn io::Write + 'a>,
13    writer_error: Option<io::Error>,
14}
15
16impl<'a> Emitter<'a> {
17    /// Create an emitter with default configuration.
18    ///
19    /// If a custom configuration is needed, use [`EmitterBuilder`] to build an
20    /// `Emitter` instance.
21    ///
22    /// [`EmitterBuilder`]: struct.EmitterBuilder.html
23    pub fn new<W: io::Write + 'a>(writer: W) -> Result<Box<Self>, EmitterError> {
24        let mut inner = unsafe { mem::MaybeUninit::zeroed().assume_init() };
25
26        if unsafe { sys::yaml_emitter_initialize(&mut inner) }.ok {
27            let mut emitter = Box::new(Self {
28                inner,
29                writer: Box::new(writer),
30                writer_error: None,
31            });
32
33            unsafe {
34                sys::yaml_emitter_set_output(
35                    &mut emitter.inner,
36                    write_handler,
37                    emitter.as_mut() as *mut _ as *mut _,
38                );
39            }
40
41            Ok(emitter)
42        } else {
43            Err(EmitterError::LibYamlError)
44        }
45    }
46
47    /// Emit an event.
48    pub fn emit(&mut self, event: Event) -> Result<(), EmitterError> {
49        if unsafe { sys::yaml_emitter_emit(&mut self.inner, &mut event.into_raw()?) }.ok {
50            debug_assert!(self.writer_error.is_none());
51            Ok(())
52        } else {
53            match mem::replace(&mut self.writer_error, None) {
54                Some(e) => Err(EmitterError::IoError(e)),
55                None => Err(EmitterError::LibYamlError),
56            }
57        }
58    }
59
60    /// Flush the emitter buffer to writer.
61    pub fn flush(&mut self) -> Result<(), EmitterError> {
62        if unsafe { sys::yaml_emitter_flush(&mut self.inner) }.ok {
63            Ok(())
64        } else {
65            Err(EmitterError::LibYamlError)
66        }
67    }
68
69    /// Return raw pointer to the underlying `yaml_emitter_t`.
70    pub fn as_raw_ptr(&mut self) -> *mut sys::yaml_emitter_t {
71        &mut self.inner
72    }
73}
74
75impl Drop for Emitter<'_> {
76    fn drop(&mut self) {
77        unsafe {
78            sys::yaml_emitter_delete(&mut self.inner)
79        }
80    }
81}
82
83unsafe fn write_handler(
84    data: *mut raw::c_void,
85    buffer: *mut raw::c_uchar,
86    mut size: u64,
87) -> raw::c_int {
88    let emitter = &mut *(data as *mut Emitter);
89
90    while size != 0 {
91        emitter.writer_error = emitter.writer
92            .write_all(slice::from_raw_parts(buffer, size.min(usize::MAX as _) as _))
93            .err();
94
95        size -= size.min(usize::MAX as _);
96    }
97
98    if emitter.writer_error.is_none() { 1 } else { 0 }
99}