use std::{mem, task::Poll};
use o3::buffer::storage;
use crate::Error;
pub(super) mod admitted;
pub(super) mod project;
pub(super) mod release;
pub(super) mod value;
use crate::segment::{Project, Release, input::Input, state};
use value::Value;
pub struct Document<'d> {
pub(super) input: Input<'d>,
pub(super) fields: Vec<Option<state::Value>>,
}
impl<'d> Document<'d> {
pub(super) fn new(input: Input<'d>, fields: Vec<Option<state::Value>>) -> Self {
Self { input, fields }
}
pub fn retire(&mut self, budget: &mut usize) -> Poll<()> {
self.drain(budget).0
}
#[inline(always)]
pub(super) fn drain(&mut self, budget: &mut usize) -> (Poll<()>, super::scanner::Released) {
while *budget != 0 && self.fields.pop().is_some() {
*budget -= 1;
}
if self.fields.is_empty() {
self.input.release(budget)
} else {
(Poll::Pending, super::scanner::Released::new())
}
}
pub fn release(self) -> Release<'d> {
Release { document: self }
}
pub fn field(&self, field: usize) -> crate::Result<Option<Value<'_, 'd>>> {
Ok(self
.fields
.get(field)
.ok_or(Error::Invalid)?
.as_ref()
.map(|value| Value::new(&self.input, value)))
}
pub fn u64(&self, field: usize) -> crate::Result<u64> {
self.value(field)?.u64()
}
pub fn raw(&self, field: usize) -> crate::Result<crate::Raw<storage::Shared>> {
self.value(field)?.raw()
}
pub fn project(self, field: usize) -> Project<'d> {
Project::new(self, field)
}
pub fn project_at(&mut self, field: usize) -> crate::Result<Option<Project<'d>>> {
let Some(value) = self.field(field)? else {
return Ok(None);
};
let parts = value.split()?;
Ok(Some(Project::with_parts(
mem::replace(self, Self::new(Input::empty(), Vec::new())),
parts,
)))
}
fn value(&self, field: usize) -> crate::Result<Value<'_, 'd>> {
self.field(field)?.ok_or(Error::Invalid)
}
}