#
unsafe_libyaml/
lib.rs

    1//! [![github]](https://github.com/dtolnay/unsafe-libyaml)&ensp;[![crates-io]](https://crates.io/crates/unsafe-libyaml)&ensp;[![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::unnecessary_cast,
    39    clippy::unreadable_literal,
    40    clippy::while_immutable_condition, // https://github.com/rust-lang/rust-clippy/issues/3548
    41)]
    42
    43extern crate alloc;
    44
    45use core::mem::size_of;
    46
    47mod 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]
    55mod 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
    81    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
    94    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
    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
    117    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
    127    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
    140    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
    153    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
    162    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
    168    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
    175    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
    183    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
    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
    229mod 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 {
    239        pub unsafe fn new(ptr: *mut yaml_char_t) -> Self {
    240            WriteToPtr { ptr }
    241        }
    242
    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 {
    249        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
    259trait PointerExt: Sized {
    260    fn c_offset_from(self, origin: Self) -> isize;
    261}
    262
    263impl<T> PointerExt for *const T {
    264    fn c_offset_from(self, origin: *const T) -> isize {
    265        (self as isize - origin as isize) / size_of::<T>() as isize
    266    }
    267}
    268
    269impl<T> PointerExt for *mut T {
    270    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]
    276mod macros;
    277
    278mod api;
    279mod dumper;
    280mod emitter;
    281mod loader;
    282mod ops;
    283mod parser;
    284mod reader;
    285mod scanner;
    286mod success;
    287mod writer;
    288mod yaml;
    289
    290pub 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};
    305pub use crate::dumper::{yaml_emitter_close, yaml_emitter_dump, yaml_emitter_open};
    306pub use crate::emitter::yaml_emitter_emit;
    307pub use crate::loader::yaml_parser_load;
    308pub use crate::parser::yaml_parser_parse;
    309pub use crate::scanner::yaml_parser_scan;
    310pub use crate::writer::yaml_emitter_flush;
    311pub 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)]
    320pub 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};