use std::collections::{HashMap, HashSet};
use serde_json::Value;
use super::ref_::{RefConfig, StreamPolicy};
#[derive(Debug, Clone, Default)]
pub struct StateSchema {
pub name: String,
var_to_idx: HashMap<(String, String), usize>,
defaults: Vec<Option<Value>>,
pull_refs: Vec<Option<RefConfig>>,
push_refs: Vec<Option<RefConfig>>,
shared_indices: HashSet<usize>,
stream_policies: HashMap<(String, String), StreamPolicy>,
}
impl StateSchema {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
var_to_idx: HashMap::new(),
defaults: Vec::new(),
pull_refs: Vec::new(),
push_refs: Vec::new(),
shared_indices: HashSet::new(),
stream_policies: HashMap::new(),
}
}
pub fn slot_count(&self) -> usize {
self.defaults.len()
}
pub fn get_index(&self, op: &str, var: &str) -> Option<usize> {
self.var_to_idx
.get(&(op.to_string(), var.to_string()))
.copied()
}
pub fn is_shared(&self, idx: usize) -> bool {
self.shared_indices.contains(&idx)
}
pub fn default_at(&self, idx: usize) -> Option<&Value> {
self.defaults.get(idx).and_then(|v| v.as_ref())
}
pub fn pull_ref_at(&self, idx: usize) -> Option<&RefConfig> {
self.pull_refs.get(idx).and_then(|v| v.as_ref())
}
pub fn push_ref_at(&self, idx: usize) -> Option<&RefConfig> {
self.push_refs.get(idx).and_then(|v| v.as_ref())
}
pub fn stream_policy(&self, op: &str, var: &str) -> Option<StreamPolicy> {
self.stream_policies
.get(&(op.to_string(), var.to_string()))
.copied()
}
#[doc(hidden)]
pub(crate) fn register_slot(
&mut self,
op: impl Into<String>,
var: impl Into<String>,
default: Option<Value>,
is_shared: bool,
) -> usize {
let key = (op.into(), var.into());
if let Some(&idx) = self.var_to_idx.get(&key) {
return idx;
}
let idx = self.defaults.len();
self.var_to_idx.insert(key, idx);
self.defaults.push(default);
self.pull_refs.push(None);
self.push_refs.push(None);
if is_shared {
self.shared_indices.insert(idx);
}
idx
}
#[doc(hidden)]
pub(crate) fn set_pull_ref(&mut self, idx: usize, pull: RefConfig) {
if let Some(slot) = self.pull_refs.get_mut(idx) {
*slot = Some(pull);
}
}
#[doc(hidden)]
pub(crate) fn set_push_ref(&mut self, idx: usize, push: RefConfig) {
if let Some(slot) = self.push_refs.get_mut(idx) {
*slot = Some(push);
}
}
#[doc(hidden)]
pub(crate) fn set_stream_policy(
&mut self,
op: impl Into<String>,
var: impl Into<String>,
policy: StreamPolicy,
) {
self.stream_policies.insert((op.into(), var.into()), policy);
}
}