1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use std::{alloc, ffi, ptr};
use std::{alloc::Layout, mem::align_of};

pub unsafe fn ts_set_allocator(
    _new_malloc: Option<unsafe extern "C" fn(usize) -> *mut std::ffi::c_void>,
    _new_calloc: Option<unsafe extern "C" fn(usize, usize) -> *mut std::ffi::c_void>,
    _new_realloc: Option<
        unsafe extern "C" fn(*mut std::ffi::c_void, usize) -> *mut std::ffi::c_void,
    >,
    _new_free: Option<unsafe extern "C" fn(*mut std::ffi::c_void)>,
) {
}
// Private
#[inline]
pub(crate) unsafe extern "C" fn ts_malloc(size: usize) -> *mut ffi::c_void {
    if size == 0 {
        return ptr::null_mut();
    }

    let (layout, offset_data) = Layout::new::<Layout>()
        .extend(Layout::from_size_align(size, align_of::<*const u8>() * 2).unwrap())
        .unwrap();
    let result = alloc::alloc(layout);
    if result.is_null() {
        panic!("tree-sitter failed to allocate {} bytes", size);
    }

    *(result as *mut Layout) = layout;
    (result as *mut u8).offset(offset_data as isize) as *mut ffi::c_void
}

#[inline]
pub(crate) unsafe extern "C" fn ts_calloc(count: usize, size: usize) -> *mut ffi::c_void {
    if count == 0 || size == 0 {
        return ptr::null_mut();
    }

    let (layout, offset_data) = Layout::new::<Layout>()
        .extend(Layout::from_size_align(size * count, align_of::<*const u8>() * 2).unwrap())
        .unwrap();
    let result = alloc::alloc_zeroed(layout);
    if result.is_null() {
        panic!("tree-sitter failed to allocate {} bytes", size);
    }

    *(result as *mut Layout) = layout;
    (result as *mut u8).offset(offset_data as isize) as *mut ffi::c_void
}

#[inline]
pub(crate) unsafe extern "C" fn ts_realloc(
    buffer: *mut ffi::c_void,
    size: usize,
) -> *mut ffi::c_void {
    if buffer.is_null() {
        ts_malloc(size)
    } else if size == 0 {
        ts_free(buffer);
        ptr::null_mut()
    } else {
        let (_, layout_offset) = Layout::new::<Layout>()
            .extend(Layout::from_size_align(0, align_of::<*const u8>() * 2).unwrap())
            .unwrap();

        let buffer = (buffer as *mut u8).offset(-(layout_offset as isize));
        let layout = *(buffer as *mut Layout);

        let (new_layout, offset_data) = Layout::new::<Layout>()
            .extend(Layout::from_size_align(size, layout.align()).unwrap())
            .unwrap();

        let result = alloc::realloc(buffer, layout, new_layout.size());
        if result.is_null() {
            panic!("tree-sitter failed to reallocate {} bytes", size);
        }

        *(result as *mut Layout) = new_layout;
        (result as *mut u8).offset(offset_data as isize) as *mut ffi::c_void
    }
}

#[inline]
pub(crate) unsafe extern "C" fn ts_free(buffer: *mut ffi::c_void) {
    if buffer.is_null() {
        return;
    }

    let (_, layout_offset) = Layout::new::<Layout>()
        .extend(Layout::from_size_align(0, align_of::<*const u8>() * 2).unwrap())
        .unwrap();

    let buffer = (buffer as *mut u8).offset(-(layout_offset as isize));
    let layout = *(buffer as *mut Layout);

    alloc::dealloc(buffer, layout);
}