gproxy-protocol 4.1.3

GPROXY v4 connection modelling, operation declarations, vendor wire types and pairwise conversion
Documentation
use super::{
    items::{Item, item_id},
    *,
};

impl ResponsesStreamCollector {
    pub(super) fn seed_output(
        &mut self,
        output: &[r::ResponseOutputItem],
    ) -> Result<(), TransformError> {
        for value in output {
            if let Some(id) = item_id(value)
                && (id.is_empty() || !self.ids.insert(id.to_owned()))
            {
                return Err(invalid("snapshot contains empty or duplicate item ID"));
            }
            let (text, json) = super::lifecycle::item_sizes(value);
            self.charge(text, false)?;
            self.charge(json, true)?;
            self.items.push(Item::new(value.clone()));
        }
        Ok(())
    }
    pub(super) fn snapshot_output(
        &self,
        output: &[r::ResponseOutputItem],
    ) -> Result<(), TransformError> {
        if output.is_empty() {
            return Ok(());
        }
        if output.len() != self.items.len() {
            return Err(invalid(
                "nonterminal snapshot output count differs from observed item lifecycle",
            ));
        }
        for (observed, snapshot) in self.items.iter().zip(output) {
            if observed.done {
                if &observed.value != snapshot {
                    return Err(invalid("snapshot changed completed item"));
                }
                continue;
            }
            let mut expected = observed.value.clone();
            for ((summary, index), part) in &observed.parts {
                let index =
                    usize::try_from(*index).map_err(|_| invalid("negative snapshot part index"))?;
                match (&mut expected, &part.value, *summary) {
                    (
                        r::ResponseOutputItem::Message(value),
                        s::OutputContentPart::Text(part),
                        false,
                    ) => {
                        if index != value.content.len() {
                            return Err(invalid("snapshot content index mismatch"));
                        }
                        value.content.push(i::OutputContent::Text(part.clone()));
                    }
                    (
                        r::ResponseOutputItem::Message(value),
                        s::OutputContentPart::Refusal(part),
                        false,
                    ) => {
                        if index != value.content.len() {
                            return Err(invalid("snapshot content index mismatch"));
                        }
                        value.content.push(i::OutputContent::Refusal(part.clone()));
                    }
                    (
                        r::ResponseOutputItem::Reasoning(value),
                        s::OutputContentPart::Reasoning(part),
                        true,
                    ) => {
                        if index != value.summary.len() {
                            return Err(invalid("snapshot summary index mismatch"));
                        }
                        value.summary.push(
                            i::SummaryText::builder(
                                i::SummaryTextType::SummaryText,
                                part.text.clone(),
                            )
                            .build(),
                        );
                    }
                    (
                        r::ResponseOutputItem::Reasoning(value),
                        s::OutputContentPart::Reasoning(part),
                        false,
                    ) => {
                        let content = value.content.get_or_insert_with(Vec::new);
                        if index != content.len() {
                            return Err(invalid("snapshot reasoning index mismatch"));
                        }
                        content.push(
                            i::ReasoningContent::builder(
                                i::ReasoningTextType::ReasoningText,
                                part.text.clone(),
                            )
                            .build(),
                        );
                    }
                    _ => return Err(invalid("snapshot part type mismatch")),
                }
            }
            if &expected != snapshot {
                return Err(invalid(
                    "nonterminal snapshot contradicts accumulated native items",
                ));
            }
        }
        Ok(())
    }
}