tectonic_engine_bibtex 0.2.1

The `bibtex` program as a reusable crate.
Documentation
use crate::c_api::{peekable::PeekableInput, xbuf::XBuf, BibNumber, StrNumber};
use std::cell::RefCell;

const MAX_BIB_FILES: usize = 20;

pub struct BibData {
    bib_file: XBuf<*mut PeekableInput>,
    bib_list: XBuf<StrNumber>,
    bib_ptr: BibNumber,
    bib_line_num: i32,
    preamble: XBuf<StrNumber>,
    preamble_ptr: BibNumber,
}

impl BibData {
    fn new() -> BibData {
        BibData {
            bib_file: XBuf::new(MAX_BIB_FILES),
            bib_list: XBuf::new(MAX_BIB_FILES),
            bib_ptr: 0,
            bib_line_num: 0,
            preamble: XBuf::new(MAX_BIB_FILES),
            preamble_ptr: 0,
        }
    }

    fn cur_bib(&self) -> StrNumber {
        self.bib_list[self.bib_ptr]
    }

    fn set_cur_bib(&mut self, num: StrNumber) {
        self.bib_list[self.bib_ptr] = num;
    }

    fn cur_bib_file(&self) -> *mut PeekableInput {
        self.bib_file[self.bib_ptr]
    }

    fn set_cur_bib_file(&mut self, input: *mut PeekableInput) {
        self.bib_file[self.bib_ptr] = input;
    }

    fn grow(&mut self) {
        self.bib_list.grow(MAX_BIB_FILES);
        self.bib_file.grow(MAX_BIB_FILES);
        self.preamble.grow(MAX_BIB_FILES);
    }
}

thread_local! {
    pub static BIBS: RefCell<BibData> = RefCell::new(BibData::new());
}

fn with_bibs<T>(f: impl FnOnce(&BibData) -> T) -> T {
    BIBS.with(|bibs| f(&bibs.borrow()))
}

fn with_bibs_mut<T>(f: impl FnOnce(&mut BibData) -> T) -> T {
    BIBS.with(|bibs| f(&mut bibs.borrow_mut()))
}

pub fn reset() {
    BIBS.with(|bibs| *bibs.borrow_mut() = BibData::new());
}

#[no_mangle]
pub extern "C" fn cur_bib() -> StrNumber {
    with_bibs(|bibs| bibs.cur_bib())
}

#[no_mangle]
pub extern "C" fn set_cur_bib(num: StrNumber) {
    with_bibs_mut(|bibs| bibs.set_cur_bib(num))
}

#[no_mangle]
pub extern "C" fn cur_bib_file() -> *mut PeekableInput {
    with_bibs(|bibs| bibs.cur_bib_file())
}

#[no_mangle]
pub extern "C" fn set_cur_bib_file(input: *mut PeekableInput) {
    with_bibs_mut(|bibs| bibs.set_cur_bib_file(input))
}

#[no_mangle]
pub extern "C" fn bib_ptr() -> BibNumber {
    with_bibs(|bibs| bibs.bib_ptr)
}

#[no_mangle]
pub extern "C" fn set_bib_ptr(num: BibNumber) {
    with_bibs_mut(|bibs| bibs.bib_ptr = num)
}

#[no_mangle]
pub extern "C" fn check_bib_files(ptr: BibNumber) {
    with_bibs_mut(|bibs| {
        if ptr == bibs.bib_list.len() {
            bibs.grow();
        }
    })
}

#[no_mangle]
pub extern "C" fn add_preamble(num: StrNumber) {
    with_bibs_mut(|bibs| {
        bibs.preamble[bibs.preamble_ptr] = num;
        bibs.preamble_ptr += 1;
    })
}

#[no_mangle]
pub extern "C" fn cur_preamble() -> StrNumber {
    with_bibs(|bibs| bibs.preamble[bibs.preamble_ptr])
}

#[no_mangle]
pub extern "C" fn preamble_ptr() -> BibNumber {
    with_bibs(|bibs| bibs.preamble_ptr)
}

#[no_mangle]
pub extern "C" fn set_preamble_ptr(num: BibNumber) {
    with_bibs_mut(|bibs| bibs.preamble_ptr = num)
}

#[no_mangle]
pub extern "C" fn bib_line_num() -> i32 {
    with_bibs(|bibs| bibs.bib_line_num)
}

#[no_mangle]
pub extern "C" fn set_bib_line_num(num: i32) {
    with_bibs_mut(|bibs| bibs.bib_line_num = num)
}