1 //! [![github]](https://github.com/dtolnay/unsafe-libyaml) [![crates-io]](https://crates.io/crates/unsafe-libyaml) [![docs-rs]](https://docs.rs/unsafe-libyaml)
2 //!
3 //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4 //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5 //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6 
7 #![no_std]
8 #![doc(html_root_url = "https://docs.rs/unsafe-libyaml/0.2.10")]
9 #![allow(non_camel_case_types, non_snake_case)]
10 #![warn(clippy::pedantic)]
11 #![allow(
12     clippy::bool_to_int_with_if,
13     clippy::cast_lossless,
14     clippy::cast_possible_truncation,
15     clippy::cast_possible_wrap,
16     clippy::cast_ptr_alignment,
17     clippy::cast_sign_loss,
18     clippy::collapsible_if,
19     clippy::doc_markdown,
20     clippy::fn_params_excessive_bools,
21     clippy::if_not_else,
22     clippy::items_after_statements,
23     clippy::let_underscore_untyped,
24     clippy::manual_range_contains,
25     clippy::manual_swap,
26     clippy::missing_panics_doc,
27     clippy::missing_safety_doc,
28     clippy::module_name_repetitions,
29     clippy::must_use_candidate,
30     clippy::nonminimal_bool,
31     clippy::ptr_as_ptr,
32     clippy::redundant_else,
33     clippy::similar_names,
34     clippy::single_match,
35     clippy::single_match_else,
36     clippy::too_many_arguments,
37     clippy::too_many_lines,
38     clippy::unnecessary_cast,
39     clippy::unreadable_literal,
40     clippy::while_immutable_condition, // https://github.com/rust-lang/rust-clippy/issues/3548
41 )]
42 
43 extern crate alloc;
44 
45 use core::mem::size_of;
46 
47 mod libc {
48     pub use core::ffi::c_void;
49     pub use core::primitive::{
50         i32 as c_int, i64 as c_long, i8 as c_char, u32 as c_uint, u64 as c_ulong, u8 as c_uchar,
51     };
52 }
53 
54 #[macro_use]
55 mod externs {
56     use crate::libc;
57     use crate::ops::{die, ForceAdd as _, ForceInto as _};
58     use alloc::alloc::{self as rust, Layout};
59     use core::mem::{self, MaybeUninit};
60     use core::ptr;
61     use core::slice;
62 
63     const HEADER: usize = {
64         let need_len = mem::size_of::<usize>();
65         // Round up to multiple of MALLOC_ALIGN.
66         (need_len + MALLOC_ALIGN - 1) & !(MALLOC_ALIGN - 1)
67     };
68 
69     // `max_align_t` may be bigger than this, but libyaml does not use `long
70     // double` or u128.
71     const MALLOC_ALIGN: usize = {
72         let int_align = mem::align_of::<libc::c_ulong>();
73         let ptr_align = mem::align_of::<usize>();
74         if int_align >= ptr_align {
75             int_align
76         } else {
77             ptr_align
78         }
79     };
80 
malloc(size: libc::c_ulong) -> *mut libc::c_void81     pub unsafe fn malloc(size: libc::c_ulong) -> *mut libc::c_void {
82         let size = HEADER.force_add(size.force_into());
83         let layout = Layout::from_size_align(size, MALLOC_ALIGN)
84             .ok()
85             .unwrap_or_else(die);
86         let memory = rust::alloc(layout);
87         if memory.is_null() {
88             rust::handle_alloc_error(layout);
89         }
90         memory.cast::<usize>().write(size);
91         memory.add(HEADER).cast()
92     }
93 
realloc(ptr: *mut libc::c_void, new_size: libc::c_ulong) -> *mut libc::c_void94     pub unsafe fn realloc(ptr: *mut libc::c_void, new_size: libc::c_ulong) -> *mut libc::c_void {
95         let mut memory = ptr.cast::<u8>().sub(HEADER);
96         let size = memory.cast::<usize>().read();
97         let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
98         let new_size = HEADER.force_add(new_size.force_into());
99         let new_layout = Layout::from_size_align(new_size, MALLOC_ALIGN)
100             .ok()
101             .unwrap_or_else(die);
102         memory = rust::realloc(memory, layout, new_size);
103         if memory.is_null() {
104             rust::handle_alloc_error(new_layout);
105         }
106         memory.cast::<usize>().write(new_size);
107         memory.add(HEADER).cast()
108     }
109 
free(ptr: *mut libc::c_void)110     pub unsafe fn free(ptr: *mut libc::c_void) {
111         let memory = ptr.cast::<u8>().sub(HEADER);
112         let size = memory.cast::<usize>().read();
113         let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN);
114         rust::dealloc(memory, layout);
115     }
116 
memcmp( lhs: *const libc::c_void, rhs: *const libc::c_void, count: libc::c_ulong, ) -> libc::c_int117     pub unsafe fn memcmp(
118         lhs: *const libc::c_void,
119         rhs: *const libc::c_void,
120         count: libc::c_ulong,
121     ) -> libc::c_int {
122         let lhs = slice::from_raw_parts(lhs.cast::<u8>(), count as usize);
123         let rhs = slice::from_raw_parts(rhs.cast::<u8>(), count as usize);
124         lhs.cmp(rhs) as libc::c_int
125     }
126 
memcpy( dest: *mut libc::c_void, src: *const libc::c_void, count: libc::c_ulong, ) -> *mut libc::c_void127     pub unsafe fn memcpy(
128         dest: *mut libc::c_void,
129         src: *const libc::c_void,
130         count: libc::c_ulong,
131     ) -> *mut libc::c_void {
132         ptr::copy_nonoverlapping(
133             src.cast::<MaybeUninit<u8>>(),
134             dest.cast::<MaybeUninit<u8>>(),
135             count as usize,
136         );
137         dest
138     }
139 
memmove( dest: *mut libc::c_void, src: *const libc::c_void, count: libc::c_ulong, ) -> *mut libc::c_void140     pub unsafe fn memmove(
141         dest: *mut libc::c_void,
142         src: *const libc::c_void,
143         count: libc::c_ulong,
144     ) -> *mut libc::c_void {
145         ptr::copy(
146             src.cast::<MaybeUninit<u8>>(),
147             dest.cast::<MaybeUninit<u8>>(),
148             count as usize,
149         );
150         dest
151     }
152 
memset( dest: *mut libc::c_void, ch: libc::c_int, count: libc::c_ulong, ) -> *mut libc::c_void153     pub unsafe fn memset(
154         dest: *mut libc::c_void,
155         ch: libc::c_int,
156         count: libc::c_ulong,
157     ) -> *mut libc::c_void {
158         ptr::write_bytes(dest.cast::<u8>(), ch as u8, count as usize);
159         dest
160     }
161 
strcmp(lhs: *const libc::c_char, rhs: *const libc::c_char) -> libc::c_int162     pub unsafe fn strcmp(lhs: *const libc::c_char, rhs: *const libc::c_char) -> libc::c_int {
163         let lhs = slice::from_raw_parts(lhs.cast::<u8>(), strlen(lhs) as usize);
164         let rhs = slice::from_raw_parts(rhs.cast::<u8>(), strlen(rhs) as usize);
165         lhs.cmp(rhs) as libc::c_int
166     }
167 
strdup(src: *const libc::c_char) -> *mut libc::c_char168     pub unsafe fn strdup(src: *const libc::c_char) -> *mut libc::c_char {
169         let len = strlen(src);
170         let dest = malloc(len + 1);
171         memcpy(dest, src.cast(), len + 1);
172         dest.cast()
173     }
174 
strlen(str: *const libc::c_char) -> libc::c_ulong175     pub unsafe fn strlen(str: *const libc::c_char) -> libc::c_ulong {
176         let mut end = str;
177         while *end != 0 {
178             end = end.add(1);
179         }
180         end.offset_from(str) as libc::c_ulong
181     }
182 
strncmp( lhs: *const libc::c_char, rhs: *const libc::c_char, mut count: libc::c_ulong, ) -> libc::c_int183     pub unsafe fn strncmp(
184         lhs: *const libc::c_char,
185         rhs: *const libc::c_char,
186         mut count: libc::c_ulong,
187     ) -> libc::c_int {
188         let mut lhs = lhs.cast::<u8>();
189         let mut rhs = rhs.cast::<u8>();
190         while count > 0 && *lhs != 0 && *lhs == *rhs {
191             lhs = lhs.add(1);
192             rhs = rhs.add(1);
193             count -= 1;
194         }
195         if count == 0 {
196             0
197         } else {
198             (*lhs).cmp(&*rhs) as libc::c_int
199         }
200     }
201 
202     macro_rules! __assert {
203         (false $(,)?) => {
204             $crate::externs::__assert_fail(stringify!(false), file!(), line!())
205         };
206         ($assertion:expr $(,)?) => {
207             if !$assertion {
208                 $crate::externs::__assert_fail(stringify!($assertion), file!(), line!());
209             }
210         };
211     }
212 
__assert_fail( __assertion: &'static str, __file: &'static str, __line: u32, ) -> !213     pub(crate) unsafe fn __assert_fail(
214         __assertion: &'static str,
215         __file: &'static str,
216         __line: u32,
217     ) -> ! {
218         struct Abort;
219         impl Drop for Abort {
220             fn drop(&mut self) {
221                 panic!();
222             }
223         }
224         let _abort_on_panic = Abort;
225         panic!("{}:{}: Assertion `{}` failed.", __file, __line, __assertion);
226     }
227 }
228 
229 mod fmt {
230     use crate::yaml::yaml_char_t;
231     use core::fmt::{self, Write};
232     use core::ptr;
233 
234     pub struct WriteToPtr {
235         ptr: *mut yaml_char_t,
236     }
237 
238     impl WriteToPtr {
new(ptr: *mut yaml_char_t) -> Self239         pub unsafe fn new(ptr: *mut yaml_char_t) -> Self {
240             WriteToPtr { ptr }
241         }
242 
write_fmt(&mut self, args: fmt::Arguments)243         pub fn write_fmt(&mut self, args: fmt::Arguments) {
244             let _ = Write::write_fmt(self, args);
245         }
246     }
247 
248     impl Write for WriteToPtr {
write_str(&mut self, s: &str) -> fmt::Result249         fn write_str(&mut self, s: &str) -> fmt::Result {
250             unsafe {
251                 ptr::copy_nonoverlapping(s.as_ptr(), self.ptr, s.len());
252                 self.ptr = self.ptr.add(s.len());
253             }
254             Ok(())
255         }
256     }
257 }
258 
259 trait PointerExt: Sized {
c_offset_from(self, origin: Self) -> isize260     fn c_offset_from(self, origin: Self) -> isize;
261 }
262 
263 impl<T> PointerExt for *const T {
c_offset_from(self, origin: *const T) -> isize264     fn c_offset_from(self, origin: *const T) -> isize {
265         (self as isize - origin as isize) / size_of::<T>() as isize
266     }
267 }
268 
269 impl<T> PointerExt for *mut T {
c_offset_from(self, origin: *mut T) -> isize270     fn c_offset_from(self, origin: *mut T) -> isize {
271         (self as isize - origin as isize) / size_of::<T>() as isize
272     }
273 }
274 
275 #[macro_use]
276 mod macros;
277 
278 mod api;
279 mod dumper;
280 mod emitter;
281 mod loader;
282 mod ops;
283 mod parser;
284 mod reader;
285 mod scanner;
286 mod success;
287 mod writer;
288 mod yaml;
289 
290 pub use crate::api::{
291     yaml_alias_event_initialize, yaml_document_add_mapping, yaml_document_add_scalar,
292     yaml_document_add_sequence, yaml_document_append_mapping_pair,
293     yaml_document_append_sequence_item, yaml_document_delete, yaml_document_end_event_initialize,
294     yaml_document_get_node, yaml_document_get_root_node, yaml_document_initialize,
295     yaml_document_start_event_initialize, yaml_emitter_delete, yaml_emitter_initialize,
296     yaml_emitter_set_break, yaml_emitter_set_canonical, yaml_emitter_set_encoding,
297     yaml_emitter_set_indent, yaml_emitter_set_output, yaml_emitter_set_output_string,
298     yaml_emitter_set_unicode, yaml_emitter_set_width, yaml_event_delete,
299     yaml_mapping_end_event_initialize, yaml_mapping_start_event_initialize, yaml_parser_delete,
300     yaml_parser_initialize, yaml_parser_set_encoding, yaml_parser_set_input,
301     yaml_parser_set_input_string, yaml_scalar_event_initialize, yaml_sequence_end_event_initialize,
302     yaml_sequence_start_event_initialize, yaml_stream_end_event_initialize,
303     yaml_stream_start_event_initialize, yaml_token_delete,
304 };
305 pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open};
306 pub use crate::emitter::yaml_emitter_emit;
307 pub use crate::loader::yaml_parser_load;
308 pub use crate::parser::yaml_parser_parse;
309 pub use crate::scanner::yaml_parser_scan;
310 pub use crate::writer::yaml_emitter_flush;
311 pub use crate::yaml::{
312     yaml_alias_data_t, yaml_break_t, yaml_document_t, yaml_emitter_state_t, yaml_emitter_t,
313     yaml_encoding_t, yaml_error_type_t, yaml_event_t, yaml_event_type_t, yaml_mapping_style_t,
314     yaml_mark_t, yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_node_type_t,
315     yaml_parser_state_t, yaml_parser_t, yaml_read_handler_t, yaml_scalar_style_t,
316     yaml_sequence_style_t, yaml_simple_key_t, yaml_stack_t, yaml_tag_directive_t, yaml_token_t,
317     yaml_token_type_t, yaml_version_directive_t, yaml_write_handler_t,
318 };
319 #[doc(hidden)]
320 pub use crate::yaml::{
321     yaml_break_t::*, yaml_emitter_state_t::*, yaml_encoding_t::*, yaml_error_type_t::*,
322     yaml_event_type_t::*, yaml_mapping_style_t::*, yaml_node_type_t::*, yaml_parser_state_t::*,
323     yaml_scalar_style_t::*, yaml_sequence_style_t::*, yaml_token_type_t::*,
324 };
325