tectonic_engine_bibtex 0.2.1

The `bibtex` program as a reusable crate.
Documentation
use crate::c_api::{xbuf::XBuf, FieldLoc, FnDefLoc, HashPointer2, StrNumber, WizFnLoc};
use std::cell::RefCell;

const WIZ_FN_SPACE: usize = 3000;
const MAX_FIELDS: usize = 17250;

pub struct OtherData {
    wiz_functions: XBuf<HashPointer2>,
    wiz_def_ptr: WizFnLoc,
    field_info: XBuf<StrNumber>,
    num_fields: FieldLoc,
    num_pre_defined_fields: FieldLoc,
    crossref_num: FieldLoc,
}

impl OtherData {
    fn new() -> OtherData {
        OtherData {
            wiz_functions: XBuf::new(WIZ_FN_SPACE),
            wiz_def_ptr: 0,
            field_info: XBuf::new(MAX_FIELDS),
            num_fields: 0,
            num_pre_defined_fields: 0,
            crossref_num: 0,
        }
    }

    pub fn field(&self, pos: usize) -> StrNumber {
        self.field_info[pos]
    }

    pub fn num_fields(&self) -> FieldLoc {
        self.num_fields
    }

    pub fn set_num_fields(&mut self, val: FieldLoc) {
        self.num_fields = val;
    }

    pub fn set_pre_defined_fields(&mut self, val: FieldLoc) {
        self.num_pre_defined_fields = val;
    }

    pub fn check_field_overflow(&mut self, fields: usize) {
        if fields > self.field_info.len() {
            self.field_info.grow(MAX_FIELDS);
        }
    }

    pub fn set_crossref_num(&mut self, val: FieldLoc) {
        self.crossref_num = val;
    }
}

thread_local! {
    pub static OTHER: RefCell<OtherData> = RefCell::new(OtherData::new());
}

pub fn reset() {
    OTHER.with(|other| *other.borrow_mut() = OtherData::new());
}

pub fn with_other<T>(f: impl FnOnce(&OtherData) -> T) -> T {
    OTHER.with(|other| f(&other.borrow()))
}

pub fn with_other_mut<T>(f: impl FnOnce(&mut OtherData) -> T) -> T {
    OTHER.with(|other| f(&mut other.borrow_mut()))
}

#[no_mangle]
pub extern "C" fn wiz_functions(pos: WizFnLoc) -> HashPointer2 {
    with_other(|other| other.wiz_functions[pos])
}

#[no_mangle]
pub extern "C" fn set_wiz_functions(pos: WizFnLoc, val: HashPointer2) {
    with_other_mut(|other| other.wiz_functions[pos] = val)
}

#[no_mangle]
pub extern "C" fn wiz_def_ptr() -> WizFnLoc {
    with_other(|other| other.wiz_def_ptr)
}

#[no_mangle]
pub extern "C" fn set_wiz_def_ptr(val: WizFnLoc) {
    with_other_mut(|other| other.wiz_def_ptr = val)
}

#[no_mangle]
pub extern "C" fn check_grow_wiz(ptr: FnDefLoc) {
    with_other_mut(|other| {
        while ptr + other.wiz_def_ptr > other.wiz_functions.len() {
            other.wiz_functions.grow(WIZ_FN_SPACE)
        }
    })
}

#[no_mangle]
pub extern "C" fn field_info(pos: FieldLoc) -> StrNumber {
    with_other(|other| other.field_info[pos])
}

#[no_mangle]
pub extern "C" fn set_field_info(pos: FieldLoc, val: StrNumber) {
    with_other_mut(|other| other.field_info[pos] = val)
}

#[no_mangle]
pub extern "C" fn check_field_overflow(total_fields: usize) {
    with_other_mut(|other| other.check_field_overflow(total_fields))
}

#[no_mangle]
pub extern "C" fn max_fields() -> usize {
    with_other(|other| other.field_info.len())
}

#[no_mangle]
pub extern "C" fn num_fields() -> FieldLoc {
    with_other(|other| other.num_fields)
}

#[no_mangle]
pub extern "C" fn set_num_fields(val: FieldLoc) {
    with_other_mut(|other| other.num_fields = val)
}

#[no_mangle]
pub extern "C" fn num_pre_defined_fields() -> FieldLoc {
    with_other(|other| other.num_pre_defined_fields)
}

#[no_mangle]
pub extern "C" fn crossref_num() -> FieldLoc {
    with_other(|other| other.crossref_num)
}