use super::{
DrainedPluginEffectReport, PluginBufferEditProposal, PluginEffect, PluginEffectBatchLimit,
PluginEffectCommitError, PluginEffectDiscardReport,
};
use crate::{
StatusInfoText,
ecs::{
components::buffer::ViewEntity,
events::status::{StatusMessage, StatusMessageRequested},
},
plugin::PluginIdentity,
};
use std::fmt::{Debug, Formatter};
#[derive(Eq, PartialEq)]
pub struct PendingPluginUpdateBatch {
identity: PluginIdentity,
limit: PluginEffectBatchLimit,
effects: Vec<PluginEffect>,
}
impl PendingPluginUpdateBatch {
#[must_use]
pub const fn new(identity: PluginIdentity, limit: PluginEffectBatchLimit) -> Self {
Self::from_validated_limit(identity, limit)
}
#[must_use]
pub(in crate::plugin) const fn from_validated_limit(
identity: PluginIdentity,
limit: PluginEffectBatchLimit,
) -> Self {
Self {
identity,
limit,
effects: Vec::new(),
}
}
#[must_use]
pub fn identity(&self) -> &str {
self.identity_proof().as_str()
}
#[must_use]
pub const fn identity_proof(&self) -> &PluginIdentity {
&self.identity
}
fn push(&mut self, effect: PluginEffect) -> Result<(), PluginEffectCommitError> {
if self.effects.len() >= self.limit.max_effects() {
return Err(PluginEffectCommitError::TooManyEffects {
identity: self.identity.clone(),
limit: self.limit.max_effects_limit(),
});
}
self.effects.push(effect);
Ok(())
}
pub fn propose_buffer_edit(
&mut self,
effect: PluginBufferEditProposal,
) -> Result<(), PluginEffectCommitError> {
self.push(PluginEffect::BufferEdit(effect))
}
pub fn push_status_text(
&mut self,
target: ViewEntity,
text: impl AsRef<str>,
) -> Result<(), PluginEffectCommitError> {
self.push(PluginEffect::Status(StatusMessageRequested {
target,
message: StatusMessage::Info(StatusInfoText::escaped_display(text)),
}))
}
#[must_use]
pub const fn effect_count(&self) -> usize {
self.effects.len()
}
#[must_use]
pub fn seal(self) -> SealedPluginEffectBatch {
SealedPluginEffectBatch {
identity: self.identity,
effects: self.effects,
}
}
#[must_use]
pub fn discard(self) -> PluginEffectDiscardReport {
PluginEffectDiscardReport::new(self.identity, self.effects.len())
}
}
impl Debug for PendingPluginUpdateBatch {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("PendingPluginUpdateBatch")
.field("identity", &self.identity)
.field("limit", &self.limit)
.field("effect_count", &self.effects.len())
.field(
"effect_shapes",
&self
.effects
.iter()
.map(PluginEffect::shape)
.collect::<Vec<_>>(),
)
.finish()
}
}
#[derive(Eq, PartialEq)]
pub struct SealedPluginEffectBatch {
identity: PluginIdentity,
effects: Vec<PluginEffect>,
}
impl SealedPluginEffectBatch {
#[must_use]
pub fn identity(&self) -> &str {
self.identity_proof().as_str()
}
#[must_use]
pub const fn identity_proof(&self) -> &PluginIdentity {
&self.identity
}
#[must_use]
pub const fn effect_count(&self) -> usize {
self.effects.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.effects.is_empty()
}
#[must_use]
pub fn discard(self) -> PluginEffectDiscardReport {
PluginEffectDiscardReport::new(self.identity, self.effects.len())
}
#[must_use]
pub fn drain(self) -> DrainedPluginEffectReport {
let mut buffer_edits = Vec::new();
let mut status_messages = Vec::new();
for effect in self.effects {
match effect {
PluginEffect::BufferEdit(effect) => {
buffer_edits.push(effect.into_request(&self.identity));
}
PluginEffect::Status(request) => status_messages.push(request),
}
}
DrainedPluginEffectReport::from_requests(self.identity, buffer_edits, status_messages)
}
}
impl Debug for SealedPluginEffectBatch {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("SealedPluginEffectBatch")
.field("identity", &self.identity)
.field("effect_count", &self.effects.len())
.field(
"effect_shapes",
&self
.effects
.iter()
.map(PluginEffect::shape)
.collect::<Vec<_>>(),
)
.finish()
}
}