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