#[cfg(feature = "doc")]
use std::sync::OnceLock;
#[derive(Clone, Copy, Debug)]
pub struct ItemDoc {
pub text: Option<&'static str>,
pub offset: u32,
pub len: u32,
}
impl ItemDoc {
pub const NONE: Self = Self {
text: None,
offset: 0,
len: 0,
};
pub const EMPTY: Self = Self {
text: None,
offset: u32::MAX,
len: 0,
};
#[must_use]
pub const fn static_text(text: &'static str) -> Self {
Self {
text: Some(text),
offset: 0,
len: 0,
}
}
#[must_use]
pub const fn is_db(self) -> bool {
self.len != 0
}
#[must_use]
pub const fn db(key: &str) -> Self {
#[cfg(feature = "doc")]
if let Some(doc) = rustpython_doc::get(key) {
return Self {
text: None,
offset: doc.offset,
len: doc.len,
};
}
#[cfg(not(feature = "doc"))]
let _ = key;
Self::NONE
}
}
impl Default for ItemDoc {
fn default() -> Self {
Self::NONE
}
}
#[inline(never)]
#[must_use]
pub fn db_doc(offset: u32, len: u32) -> Option<&'static str> {
if len == 0 {
return None;
}
db_slice(offset, len)
}
#[inline(never)]
#[must_use]
pub fn plain_doc(doc: ItemDoc) -> Option<&'static str> {
if doc.offset == u32::MAX && doc.len == 0 {
return Some("");
}
if doc.len != 0 {
return db_doc(doc.offset, doc.len);
}
doc.text.filter(|text| !text.is_empty())
}
#[cfg(feature = "doc")]
#[inline(never)]
fn db_slice(offset: u32, len: u32) -> Option<&'static str> {
let text = docs();
let start = offset as usize;
let end = start.checked_add(len as usize)?;
text.get(start..end)
}
#[cfg(not(feature = "doc"))]
fn db_slice(_offset: u32, _len: u32) -> Option<&'static str> {
None
}
#[cfg(feature = "doc")]
#[inline(never)]
fn docs() -> &'static str {
static TEXT: OnceLock<Box<str>> = OnceLock::new();
TEXT.get_or_init(|| {
let bytes = match xz::decode_all(rustpython_doc::BLOB) {
Ok(bytes) => bytes,
Err(_) => panic!("doc blob"),
};
match String::from_utf8(bytes) {
Ok(text) => text.into_boxed_str(),
Err(_) => panic!("doc blob"),
}
})
.as_ref()
}
#[cfg(test)]
mod tests {
use super::{ItemDoc, plain_doc};
#[test]
fn explicit_empty_doc_is_empty_string() {
assert_eq!(plain_doc(ItemDoc::EMPTY), Some(""));
assert_eq!(plain_doc(ItemDoc::NONE), None);
assert_eq!(plain_doc(ItemDoc::static_text("")), None);
assert_eq!(plain_doc(ItemDoc::static_text("a")), Some("a"));
}
}