//! [![github]](https://github.com/dtolnay/unsafe-libyaml) [![crates-io]](https://crates.io/crates/unsafe-libyaml) [![docs-rs]](https://docs.rs/unsafe-libyaml) //! //! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github //! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust //! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs #![no_std] #![doc(html_root_url = "https://docs.rs/unsafe-libyaml/0.2.10")] #![allow(non_camel_case_types, non_snake_case)] #![warn(clippy::pedantic)] #![allow( clippy::bool_to_int_with_if, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::collapsible_if, clippy::doc_markdown, clippy::fn_params_excessive_bools, clippy::if_not_else, clippy::items_after_statements, clippy::let_underscore_untyped, clippy::manual_range_contains, clippy::manual_swap, clippy::missing_panics_doc, clippy::missing_safety_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::nonminimal_bool, clippy::ptr_as_ptr, clippy::redundant_else, clippy::similar_names, clippy::single_match, clippy::single_match_else, clippy::too_many_arguments, clippy::too_many_lines, clippy::unnecessary_cast, clippy::unreadable_literal, clippy::while_immutable_condition, // https://github.com/rust-lang/rust-clippy/issues/3548 )] extern crate alloc; use core::mem::size_of; mod libc { pub use core::ffi::c_void; pub use core::primitive::{ i32 as c_int, i64 as c_long, i8 as c_char, u32 as c_uint, u64 as c_ulong, u8 as c_uchar, }; } #[macro_use] mod externs { use crate::libc; use crate::ops::{die, ForceAdd as _, ForceInto as _}; use alloc::alloc::{self as rust, Layout}; use core::mem::{self, MaybeUninit}; use core::ptr; use core::slice; const HEADER: usize = { let need_len = mem::size_of::(); // Round up to multiple of MALLOC_ALIGN. (need_len + MALLOC_ALIGN - 1) & !(MALLOC_ALIGN - 1) }; // `max_align_t` may be bigger than this, but libyaml does not use `long // double` or u128. const MALLOC_ALIGN: usize = { let int_align = mem::align_of::(); let ptr_align = mem::align_of::(); if int_align >= ptr_align { int_align } else { ptr_align } }; pub unsafe fn malloc(size: libc::c_ulong) -> *mut libc::c_void { let size = HEADER.force_add(size.force_into()); let layout = Layout::from_size_align(size, MALLOC_ALIGN) .ok() .unwrap_or_else(die); let memory = rust::alloc(layout); if memory.is_null() { rust::handle_alloc_error(layout); } memory.cast::().write(size); memory.add(HEADER).cast() } pub unsafe fn realloc(ptr: *mut libc::c_void, new_size: libc::c_ulong) -> *mut libc::c_void { let mut memory = ptr.cast::().sub(HEADER); let size = memory.cast::().read(); let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN); let new_size = HEADER.force_add(new_size.force_into()); let new_layout = Layout::from_size_align(new_size, MALLOC_ALIGN) .ok() .unwrap_or_else(die); memory = rust::realloc(memory, layout, new_size); if memory.is_null() { rust::handle_alloc_error(new_layout); } memory.cast::().write(new_size); memory.add(HEADER).cast() } pub unsafe fn free(ptr: *mut libc::c_void) { let memory = ptr.cast::().sub(HEADER); let size = memory.cast::().read(); let layout = Layout::from_size_align_unchecked(size, MALLOC_ALIGN); rust::dealloc(memory, layout); } pub unsafe fn memcmp( lhs: *const libc::c_void, rhs: *const libc::c_void, count: libc::c_ulong, ) -> libc::c_int { let lhs = slice::from_raw_parts(lhs.cast::(), count as usize); let rhs = slice::from_raw_parts(rhs.cast::(), count as usize); lhs.cmp(rhs) as libc::c_int } pub unsafe fn memcpy( dest: *mut libc::c_void, src: *const libc::c_void, count: libc::c_ulong, ) -> *mut libc::c_void { ptr::copy_nonoverlapping( src.cast::>(), dest.cast::>(), count as usize, ); dest } pub unsafe fn memmove( dest: *mut libc::c_void, src: *const libc::c_void, count: libc::c_ulong, ) -> *mut libc::c_void { ptr::copy( src.cast::>(), dest.cast::>(), count as usize, ); dest } pub unsafe fn memset( dest: *mut libc::c_void, ch: libc::c_int, count: libc::c_ulong, ) -> *mut libc::c_void { ptr::write_bytes(dest.cast::(), ch as u8, count as usize); dest } pub unsafe fn strcmp(lhs: *const libc::c_char, rhs: *const libc::c_char) -> libc::c_int { let lhs = slice::from_raw_parts(lhs.cast::(), strlen(lhs) as usize); let rhs = slice::from_raw_parts(rhs.cast::(), strlen(rhs) as usize); lhs.cmp(rhs) as libc::c_int } pub unsafe fn strdup(src: *const libc::c_char) -> *mut libc::c_char { let len = strlen(src); let dest = malloc(len + 1); memcpy(dest, src.cast(), len + 1); dest.cast() } pub unsafe fn strlen(str: *const libc::c_char) -> libc::c_ulong { let mut end = str; while *end != 0 { end = end.add(1); } end.offset_from(str) as libc::c_ulong } pub unsafe fn strncmp( lhs: *const libc::c_char, rhs: *const libc::c_char, mut count: libc::c_ulong, ) -> libc::c_int { let mut lhs = lhs.cast::(); let mut rhs = rhs.cast::(); while count > 0 && *lhs != 0 && *lhs == *rhs { lhs = lhs.add(1); rhs = rhs.add(1); count -= 1; } if count == 0 { 0 } else { (*lhs).cmp(&*rhs) as libc::c_int } } macro_rules! __assert { (false $(,)?) => { $crate::externs::__assert_fail(stringify!(false), file!(), line!()) }; ($assertion:expr $(,)?) => { if !$assertion { $crate::externs::__assert_fail(stringify!($assertion), file!(), line!()); } }; } pub(crate) unsafe fn __assert_fail( __assertion: &'static str, __file: &'static str, __line: u32, ) -> ! { struct Abort; impl Drop for Abort { fn drop(&mut self) { panic!(); } } let _abort_on_panic = Abort; panic!("{}:{}: Assertion `{}` failed.", __file, __line, __assertion); } } mod fmt { use crate::yaml::yaml_char_t; use core::fmt::{self, Write}; use core::ptr; pub struct WriteToPtr { ptr: *mut yaml_char_t, } impl WriteToPtr { pub unsafe fn new(ptr: *mut yaml_char_t) -> Self { WriteToPtr { ptr } } pub fn write_fmt(&mut self, args: fmt::Arguments) { let _ = Write::write_fmt(self, args); } } impl Write for WriteToPtr { fn write_str(&mut self, s: &str) -> fmt::Result { unsafe { ptr::copy_nonoverlapping(s.as_ptr(), self.ptr, s.len()); self.ptr = self.ptr.add(s.len()); } Ok(()) } } } trait PointerExt: Sized { fn c_offset_from(self, origin: Self) -> isize; } impl PointerExt for *const T { fn c_offset_from(self, origin: *const T) -> isize { (self as isize - origin as isize) / size_of::() as isize } } impl PointerExt for *mut T { fn c_offset_from(self, origin: *mut T) -> isize { (self as isize - origin as isize) / size_of::() as isize } } #[macro_use] mod macros; mod api; mod dumper; mod emitter; mod loader; mod ops; mod parser; mod reader; mod scanner; mod success; mod writer; mod yaml; pub use crate::api::{ yaml_alias_event_initialize, yaml_document_add_mapping, yaml_document_add_scalar, yaml_document_add_sequence, yaml_document_append_mapping_pair, yaml_document_append_sequence_item, yaml_document_delete, yaml_document_end_event_initialize, yaml_document_get_node, yaml_document_get_root_node, yaml_document_initialize, yaml_document_start_event_initialize, yaml_emitter_delete, yaml_emitter_initialize, yaml_emitter_set_break, yaml_emitter_set_canonical, yaml_emitter_set_encoding, yaml_emitter_set_indent, yaml_emitter_set_output, yaml_emitter_set_output_string, yaml_emitter_set_unicode, yaml_emitter_set_width, yaml_event_delete, yaml_mapping_end_event_initialize, yaml_mapping_start_event_initialize, yaml_parser_delete, yaml_parser_initialize, yaml_parser_set_encoding, yaml_parser_set_input, yaml_parser_set_input_string, yaml_scalar_event_initialize, yaml_sequence_end_event_initialize, yaml_sequence_start_event_initialize, yaml_stream_end_event_initialize, yaml_stream_start_event_initialize, yaml_token_delete, }; pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open}; pub use crate::emitter::yaml_emitter_emit; pub use crate::loader::yaml_parser_load; pub use crate::parser::yaml_parser_parse; pub use crate::scanner::yaml_parser_scan; pub use crate::writer::yaml_emitter_flush; pub use crate::yaml::{ yaml_alias_data_t, yaml_break_t, yaml_document_t, yaml_emitter_state_t, yaml_emitter_t, yaml_encoding_t, yaml_error_type_t, yaml_event_t, yaml_event_type_t, yaml_mapping_style_t, yaml_mark_t, yaml_node_item_t, yaml_node_pair_t, yaml_node_t, yaml_node_type_t, yaml_parser_state_t, yaml_parser_t, yaml_read_handler_t, yaml_scalar_style_t, yaml_sequence_style_t, yaml_simple_key_t, yaml_stack_t, yaml_tag_directive_t, yaml_token_t, yaml_token_type_t, yaml_version_directive_t, yaml_write_handler_t, }; #[doc(hidden)] pub use crate::yaml::{ yaml_break_t::*, yaml_emitter_state_t::*, yaml_encoding_t::*, yaml_error_type_t::*, yaml_event_type_t::*, yaml_mapping_style_t::*, yaml_node_type_t::*, yaml_parser_state_t::*, yaml_scalar_style_t::*, yaml_sequence_style_t::*, yaml_token_type_t::*, };