unsafe_libyaml_norway/
lib.rs

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