1#![allow(clippy::not_unsafe_ptr_arg_deref)]
2
3use core::ptr;
4use core::str;
5use core::{slice, slice::from_raw_parts};
6use std::ffi::{CString, c_char, c_uchar};
7
8use crate::Parser;
9use crate::parse;
10
11#[repr(C)]
12pub struct CStringWithLength {
13 pub ptr: *const c_uchar,
14 pub len: usize,
15}
16
17impl CStringWithLength {
18 fn new(value: &str) -> CStringWithLength {
19 let cstring = CString::new(value).unwrap();
20
21 CStringWithLength {
22 ptr: cstring.into_raw() as *const c_uchar,
23 len: value.len(),
24 }
25 }
26}
27
28impl From<&str> for CStringWithLength {
29 fn from(value: &str) -> Self { CStringWithLength::new(value) }
30}
31
32impl From<CStringWithLength> for &str {
33 fn from(value: CStringWithLength) -> Self {
34 unsafe { str::from_utf8_unchecked(slice::from_raw_parts(value.ptr, value.len)) }
35 }
36}
37
38#[unsafe(no_mangle)]
40pub extern "C" fn milo_has_debug() -> bool { cfg!(any(debug_assertions, feature = "debug")) }
41
42#[unsafe(no_mangle)]
47pub extern "C" fn milo_noop(_parser: &mut Parser, _at: usize, _len: usize) {}
48
49#[unsafe(no_mangle)]
52pub extern "C" fn milo_free_string(s: CStringWithLength) {
53 unsafe {
54 let _ = CString::from_raw(s.ptr as *mut c_char);
55 }
56}
57
58#[unsafe(no_mangle)]
60pub extern "C" fn milo_create() -> *mut Parser { Box::into_raw(Box::new(Parser::new())) }
61
62#[unsafe(no_mangle)]
64pub extern "C" fn milo_destroy(parser: *mut Parser) {
65 if parser.is_null() {
66 return;
67 }
68
69 unsafe {
70 let _ = Box::from_raw(parser);
71 }
72}
73
74#[unsafe(no_mangle)]
76pub extern "C" fn milo_parse(parser: *mut Parser, data: *const c_uchar, limit: usize) -> usize {
77 unsafe { (*parser).parse(data, limit) }
78}
79
80#[unsafe(no_mangle)]
92pub extern "C" fn milo_reset(parser: *mut Parser, keep_parsed: bool) { unsafe { (*parser).reset(keep_parsed) } }
93
94#[unsafe(no_mangle)]
98pub extern "C" fn milo_clear(parser: *mut Parser) { unsafe { (*parser).clear() } }
99
100#[unsafe(no_mangle)]
102pub extern "C" fn milo_pause(parser: *mut Parser) { unsafe { (*parser).pause() } }
103
104#[unsafe(no_mangle)]
106pub extern "C" fn milo_resume(parser: *mut Parser) { unsafe { (*parser).resume() } }
107
108#[unsafe(no_mangle)]
111pub extern "C" fn milo_finish(parser: *mut Parser) { unsafe { (*parser).finish() } }
112
113#[unsafe(no_mangle)]
115pub extern "C" fn milo_fail(parser: *mut Parser, code: u8, description: CStringWithLength) {
116 unsafe { (*parser).fail(code, description.into()) };
117}
118
119#[unsafe(no_mangle)]
123pub extern "C" fn milo_state_string(parser: *mut Parser) -> CStringWithLength {
124 unsafe { (*parser).state_str().into() }
125}
126
127#[unsafe(no_mangle)]
131pub extern "C" fn milo_error_code_string(parser: *mut Parser) -> CStringWithLength {
132 unsafe { (*parser).error_code_str().into() }
133}
134
135#[unsafe(no_mangle)]
139pub extern "C" fn milo_error_description_string(parser: *mut Parser) -> CStringWithLength {
140 unsafe { (*parser).error_description_str().into() }
141}