use std::{borrow::Cow, fmt, marker::PhantomData};
use bytes::Bytes;
use http::{HeaderMap, Method, StatusCode, Uri};
use serde::{
Deserialize, Deserializer,
de::{self, DeserializeOwned, DeserializeSeed, IgnoredAny, MapAccess, SeqAccess, Visitor},
};
use crate::{
codec::{self, DecodeError},
content::Content,
error::{Error, ResponseValidationError, format_endpoint},
name::Name,
response::{
Answer, Answers, ChoiceAnswer, NoulAnswer, ResponseMeta, ScoreAnswer, SystemOneResponse,
Usage, push_by_level, sort_by_level,
},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct AnswerContext {
expected_answers: u32,
levels: u32,
}
impl AnswerContext {
pub(crate) fn new(expected_answers: usize) -> Self {
Self { expected_answers: saturate(expected_answers), levels: 0 }
}
pub(crate) fn with_levels(self, levels: usize) -> Self {
Self { levels: saturate(levels.min(MAX_LEVEL_HINT)), ..self }
}
fn levels(self) -> usize {
self.levels as usize
}
#[must_use]
pub fn expected_answers(&self) -> usize {
self.expected_answers as usize
}
}
const MAX_LEVEL_HINT: usize = 8;
const MAX_OPTION_HINT: usize = 8;
fn saturate(count: usize) -> u32 {
u32::try_from(count).unwrap_or(u32::MAX)
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be decoded as the answers of a response",
label = "not a set of answers",
note = "use `Answers` to look answers up by question name, or declare a struct with one \
field per question and `#[derive(QuestionSet)]` it (the `macros` feature, on by \
default), which implements `AnswerSet`"
)]
pub trait AnswerSet: Sized {
fn deserialize_answers<'de, D>(
deserializer: D,
context: AnswerContext,
) -> Result<Self, D::Error>
where
D: Deserializer<'de>;
}
impl AnswerSet for Answers {
fn deserialize_answers<'de, D>(
deserializer: D,
context: AnswerContext,
) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(AnswersVisitor {
capacity: context.expected_answers(),
levels: context.levels(),
})
}
}
impl<'de> Deserialize<'de> for Answers {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Self::deserialize_answers(deserializer, AnswerContext::default())
}
}
struct AnswersVisitor {
capacity: usize,
levels: usize,
}
impl<'de> Visitor<'de> for AnswersVisitor {
type Value = Answers;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object of question name to answer")
}
fn visit_map<M>(self, mut map: M) -> Result<Answers, M::Error>
where
M: MapAccess<'de>,
{
let mut answers = Answers::with_capacity(self.capacity);
while let Some(name) = map.next_key_seed(TextSeed)? {
let seed = AnswerSeed::<Option<Answer>> {
name: &name,
levels: self.levels,
target: PhantomData,
};
if let Some(answer) = map.next_value_seed(seed)? {
answers.push(Name::from(name), answer);
}
}
Ok(answers)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Kind {
Noul,
Choice,
Score,
}
impl Kind {
fn name(self) -> &'static str {
match self {
Self::Noul => "noul",
Self::Choice => "choice",
Self::Score => "score",
}
}
}
enum Seen<'de> {
Known(Kind),
Unknown(Cow<'de, str>),
}
trait Target: Sized {
const EXPECTED: Option<Kind>;
fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, name: &str) -> Result<Self, E>
where
E: de::Error;
}
impl Target for Option<Answer> {
const EXPECTED: Option<Kind> = None;
fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, name: &str) -> Result<Self, E>
where
E: de::Error,
{
match seen {
Some(Seen::Known(Kind::Noul)) => members.noul().map(|answer| Some(answer.into())),
Some(Seen::Known(Kind::Choice)) => members.choice().map(|answer| Some(answer.into())),
Some(Seen::Known(Kind::Score)) => members.score().map(|answer| Some(answer.into())),
Some(Seen::Unknown(kind)) => {
#[cfg(feature = "tracing")]
tracing::warn!(
target: crate::telemetry::TARGET,
question = %crate::telemetry::ServerName(name),
answer_type = %crate::telemetry::ServerName(&kind),
"ignoring an answer of a type this version does not model; \
the raw body still carries it"
);
#[cfg(not(feature = "tracing"))]
let _ = (name, kind);
Ok(None)
}
None => Err(E::missing_field("type")),
}
}
}
impl Target for NoulAnswer {
const EXPECTED: Option<Kind> = Some(Kind::Noul);
fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
where
E: de::Error,
{
match seen {
Some(_) => members.noul(),
None => Err(E::missing_field("type")),
}
}
}
impl Target for ChoiceAnswer {
const EXPECTED: Option<Kind> = Some(Kind::Choice);
fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
where
E: de::Error,
{
match seen {
Some(_) => members.choice(),
None => Err(E::missing_field("type")),
}
}
}
impl Target for ScoreAnswer {
const EXPECTED: Option<Kind> = Some(Kind::Score);
fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
where
E: de::Error,
{
match seen {
Some(_) => members.score(),
None => Err(E::missing_field("type")),
}
}
}
impl<'de> Deserialize<'de> for NoulAnswer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
}
}
impl<'de> Deserialize<'de> for ChoiceAnswer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
}
}
impl<'de> Deserialize<'de> for ScoreAnswer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
}
}
impl<'de> Deserialize<'de> for Answer {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer
.deserialize_any(AnswerSeed::<Option<Answer>>::DETACHED)?
.ok_or_else(|| de::Error::custom("an answer of a type this version does not model"))
}
}
struct AnswerSeed<'n, T> {
name: &'n str,
levels: usize,
target: PhantomData<T>,
}
impl<T> AnswerSeed<'static, T> {
const DETACHED: Self = Self { name: "", levels: 0, target: PhantomData };
}
impl<'de, T> DeserializeSeed<'de> for AnswerSeed<'_, T>
where
T: Target,
{
type Value = T;
fn deserialize<D>(self, deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(self)
}
}
impl<'de, T> Visitor<'de> for AnswerSeed<'_, T>
where
T: Target,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an answer object")
}
fn visit_map<M>(self, mut map: M) -> Result<T, M::Error>
where
M: MapAccess<'de>,
{
let mut seen: Option<Seen<'de>> = None;
let mut members = Members { levels: self.levels, ..Members::default() };
while let Some(index) = map.next_key_seed(Member::NAMES)? {
let member = match index {
Some(0) => {
let seed = KindSeed { expected: T::EXPECTED, previous: seen.as_ref() };
seen = Some(map.next_value_seed(seed)?);
continue;
}
Some(at) => Member::DATA.get(at - 1).copied(),
None => None,
};
let Some(member) = member else {
map.next_value::<IgnoredAny>()?;
continue;
};
let known = match &seen {
Some(Seen::Known(kind)) => Some(*kind),
Some(Seen::Unknown(_)) => None,
None => T::EXPECTED,
};
match known {
Some(kind) if member.belongs_to(kind) => members.read(member, kind, &mut map)?,
None if seen.is_none() => members.hold(member, map.next_value_seed(RawSeed)?),
_ => {
map.next_value::<IgnoredAny>()?;
}
}
}
T::build(seen, members, self.name)
}
fn visit_bool<E: de::Error>(self, _: bool) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_i64<E: de::Error>(self, _: i64) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_u64<E: de::Error>(self, _: u64) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_f64<E: de::Error>(self, _: f64) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_str<E: de::Error>(self, _: &str) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_unit<E: de::Error>(self) -> Result<T, E> {
Err(E::missing_field("type"))
}
fn visit_seq<S>(self, _: S) -> Result<T, S::Error>
where
S: SeqAccess<'de>,
{
Err(de::Error::missing_field("type"))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Member {
Noul,
Choice,
Confidence,
Score,
Legend,
Probabilities,
}
impl Member {
const NAMES: KeyIn =
KeyIn(&["type", "noul", "choice", "confidence", "score", "legend", "probabilities"]);
const DATA: [Self; 6] = [
Self::Noul,
Self::Choice,
Self::Confidence,
Self::Score,
Self::Legend,
Self::Probabilities,
];
fn belongs_to(self, kind: Kind) -> bool {
match self {
Self::Noul => kind == Kind::Noul,
Self::Choice => kind == Kind::Choice,
Self::Confidence | Self::Probabilities => kind != Kind::Noul,
Self::Score | Self::Legend => kind == Kind::Score,
}
}
}
struct KindSeed<'s, 'de> {
expected: Option<Kind>,
previous: Option<&'s Seen<'de>>,
}
impl<'de> DeserializeSeed<'de> for KindSeed<'_, 'de> {
type Value = Seen<'de>;
fn deserialize<D>(self, deserializer: D) -> Result<Seen<'de>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}
impl<'de> KindSeed<'_, 'de> {
fn classify<E>(self, text: &str, keep: impl FnOnce() -> Cow<'de, str>) -> Result<Seen<'de>, E>
where
E: de::Error,
{
let seen = match text {
"noul" => Seen::Known(Kind::Noul),
"choice" => Seen::Known(Kind::Choice),
"score" => Seen::Known(Kind::Score),
_ => Seen::Unknown(keep()),
};
match (self.expected, &seen) {
(Some(expected), Seen::Known(kind)) if *kind != expected => {
return Err(wrong_kind(expected));
}
(Some(expected), Seen::Unknown(_)) => return Err(wrong_kind(expected)),
_ => {}
}
match self.previous {
Some(previous) if !previous.is_same(&seen) => Err(mixed_types()),
_ => Ok(seen),
}
}
}
fn wrong_kind<E: de::Error>(expected: Kind) -> E {
E::custom(format_args!("expected an answer of type `{}`", expected.name()))
}
impl Seen<'_> {
fn is_same(&self, other: &Seen<'_>) -> bool {
match (self, other) {
(Seen::Known(left), Seen::Known(right)) => left == right,
(Seen::Unknown(left), Seen::Unknown(right)) => left == right,
_ => false,
}
}
}
impl<'de> Visitor<'de> for KindSeed<'_, 'de> {
type Value = Seen<'de>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an answer type name")
}
fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Seen<'de>, E> {
self.classify(value, || Cow::Borrowed(value))
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Seen<'de>, E> {
self.classify(value, || Cow::Owned(value.to_owned()))
}
}
#[derive(Default)]
struct Members<'de> {
noul: Slot<'de, f64>,
choice: Slot<'de, Name>,
confidence: Slot<'de, f64>,
score: Slot<'de, f64>,
legend: Slot<'de, Vec<(u32, Content<'static>)>>,
probabilities: Probabilities<'de>,
levels: usize,
}
#[derive(Default)]
enum Slot<'de, T> {
#[default]
Missing,
Read(T),
Raw(Cow<'de, str>),
}
#[derive(Default)]
enum Probabilities<'de> {
#[default]
Missing,
Named(Vec<(Name, f64)>),
Levels(Vec<(u32, f64)>),
Raw(Cow<'de, str>),
}
impl<'de> Members<'de> {
fn read<M>(&mut self, member: Member, kind: Kind, map: &mut M) -> Result<(), M::Error>
where
M: MapAccess<'de>,
{
match member {
Member::Noul => self.noul = Slot::Read(map.next_value()?),
Member::Choice => self.choice = Slot::Read(map.next_value()?),
Member::Confidence => self.confidence = Slot::Read(map.next_value()?),
Member::Score => self.score = Slot::Read(map.next_value()?),
Member::Legend => {
let capacity = match &self.probabilities {
Probabilities::Levels(levels) => levels.len(),
_ => self.levels,
};
self.legend = Slot::Read(map.next_value_seed(LegendSeed { capacity })?);
}
Member::Probabilities if kind == Kind::Score => {
let capacity = match &self.legend {
Slot::Read(legend) => legend.len(),
_ => self.levels,
};
self.probabilities =
Probabilities::Levels(map.next_value_seed(LevelsSeed { capacity })?);
}
Member::Probabilities => {
self.probabilities = Probabilities::Named(map.next_value_seed(NamedSeed)?);
}
}
Ok(())
}
fn hold(&mut self, member: Member, raw: Cow<'de, str>) {
match member {
Member::Noul => self.noul = Slot::Raw(raw),
Member::Choice => self.choice = Slot::Raw(raw),
Member::Confidence => self.confidence = Slot::Raw(raw),
Member::Score => self.score = Slot::Raw(raw),
Member::Legend => self.legend = Slot::Raw(raw),
Member::Probabilities => self.probabilities = Probabilities::Raw(raw),
}
}
fn noul<E: de::Error>(self) -> Result<NoulAnswer, E> {
Ok(NoulAnswer::new(self.noul.resolve::<f64, E>("noul")?))
}
fn choice<E: de::Error>(self) -> Result<ChoiceAnswer, E> {
let choice = self.choice.resolve::<Name, E>("choice")?;
let confidence = self.confidence.resolve::<f64, E>("confidence")?;
let probabilities = match self.probabilities {
Probabilities::Named(named) => named,
Probabilities::Raw(raw) => decode_held::<NamedProbabilities, E>(&raw)?.0,
Probabilities::Missing => return Err(E::missing_field("probabilities")),
Probabilities::Levels(_) => return Err(mixed_types()),
};
Ok(ChoiceAnswer::from_parts(choice, confidence, probabilities))
}
fn score<E: de::Error>(self) -> Result<ScoreAnswer, E> {
let score = self.score.resolve::<f64, E>("score")?;
let confidence = self.confidence.resolve::<f64, E>("confidence")?;
let legend = self.legend.resolve::<Legend, E>("legend")?;
let probabilities = match self.probabilities {
Probabilities::Levels(levels) => levels,
Probabilities::Raw(raw) => decode_held::<LevelProbabilities, E>(&raw)?.0,
Probabilities::Missing => return Err(E::missing_field("probabilities")),
Probabilities::Named(_) => return Err(mixed_types()),
};
Ok(ScoreAnswer::from_sorted(score, confidence, legend, probabilities))
}
}
fn mixed_types<E: de::Error>() -> E {
E::custom("the answer names two different types")
}
impl<T> Slot<'_, T> {
fn resolve<W, E>(self, member: &'static str) -> Result<T, E>
where
W: DeserializeOwned + Into<T>,
E: de::Error,
{
match self {
Self::Read(value) => Ok(value),
Self::Raw(raw) => decode_held::<W, E>(&raw).map(Into::into),
Self::Missing => Err(E::missing_field(member)),
}
}
}
fn decode_held<W, E>(raw: &str) -> Result<W, E>
where
W: DeserializeOwned,
E: de::Error,
{
codec::decode(raw.as_bytes()).map_err(E::custom)
}
struct RawSeed;
impl<'de> DeserializeSeed<'de> for RawSeed {
type Value = Cow<'de, str>;
fn deserialize<D>(self, deserializer: D) -> Result<Cow<'de, str>, D::Error>
where
D: Deserializer<'de>,
{
codec::deserialize_raw(deserializer)
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct KeyIn(pub(crate) &'static [&'static str]);
impl<'de> DeserializeSeed<'de> for KeyIn {
type Value = Option<usize>;
fn deserialize<D>(self, deserializer: D) -> Result<Option<usize>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}
impl Visitor<'_> for KeyIn {
type Value = Option<usize>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object key")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Option<usize>, E> {
Ok(self.0.iter().position(|name| *name == value))
}
}
struct TextSeed;
impl<'de> DeserializeSeed<'de> for TextSeed {
type Value = Cow<'de, str>;
fn deserialize<D>(self, deserializer: D) -> Result<Cow<'de, str>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}
impl<'de> Visitor<'de> for TextSeed {
type Value = Cow<'de, str>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string")
}
fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Cow<'de, str>, E> {
Ok(Cow::Borrowed(value))
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Cow<'de, str>, E> {
Ok(Cow::Owned(value.to_owned()))
}
}
struct LevelSeed;
impl<'de> DeserializeSeed<'de> for LevelSeed {
type Value = u32;
fn deserialize<D>(self, deserializer: D) -> Result<u32, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
}
impl Visitor<'_> for LevelSeed {
type Value = u32;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a score level")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<u32, E> {
value.parse().map_err(|_| E::custom("a score level is a non-negative integer"))
}
fn visit_u64<E: de::Error>(self, value: u64) -> Result<u32, E> {
u32::try_from(value).map_err(|_| E::custom("a score level is a non-negative integer"))
}
}
struct NamedSeed;
impl<'de> DeserializeSeed<'de> for NamedSeed {
type Value = Vec<(Name, f64)>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self)
}
}
impl<'de> Visitor<'de> for NamedSeed {
type Value = Vec<(Name, f64)>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object of option name to probability")
}
fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let mut entries = Vec::with_capacity(map.size_hint().unwrap_or(0).min(MAX_OPTION_HINT));
while let Some(name) = map.next_key_seed(TextSeed)? {
let probability = map.next_value()?;
entries.push((Name::from(name), probability));
}
Ok(entries)
}
}
struct LevelsSeed {
capacity: usize,
}
impl<'de> DeserializeSeed<'de> for LevelsSeed {
type Value = Vec<(u32, f64)>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self)
}
}
impl<'de> Visitor<'de> for LevelsSeed {
type Value = Vec<(u32, f64)>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object of score level to probability")
}
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
by_level(map, self.capacity, |map| map.next_value())
}
}
struct LegendSeed {
capacity: usize,
}
impl<'de> DeserializeSeed<'de> for LegendSeed {
type Value = Vec<(u32, Content<'static>)>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self)
}
}
impl<'de> Visitor<'de> for LegendSeed {
type Value = Vec<(u32, Content<'static>)>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object of score level to description")
}
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
by_level(map, self.capacity, |map| {
map.next_value::<Content<'de>>().map(Content::into_owned)
})
}
}
fn by_level<'de, M, V>(
mut map: M,
capacity: usize,
mut value: impl FnMut(&mut M) -> Result<V, M::Error>,
) -> Result<Vec<(u32, V)>, M::Error>
where
M: MapAccess<'de>,
{
let Some(mut level) = map.next_key_seed(LevelSeed)? else {
return Ok(Vec::new());
};
let mut entries = Vec::with_capacity(capacity);
let mut in_order = true;
loop {
let read = value(&mut map)?;
push_by_level(&mut entries, &mut in_order, level, read);
match map.next_key_seed(LevelSeed)? {
Some(next) => level = next,
None => break,
}
}
if !in_order {
sort_by_level(&mut entries);
}
Ok(entries)
}
struct Legend(Vec<(u32, Content<'static>)>);
struct NamedProbabilities(Vec<(Name, f64)>);
struct LevelProbabilities(Vec<(u32, f64)>);
impl From<Legend> for Vec<(u32, Content<'static>)> {
fn from(legend: Legend) -> Self {
legend.0
}
}
impl<'de> Deserialize<'de> for Legend {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
LegendSeed { capacity: 0 }.deserialize(deserializer).map(Self)
}
}
impl<'de> Deserialize<'de> for NamedProbabilities {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
NamedSeed.deserialize(deserializer).map(Self)
}
}
impl<'de> Deserialize<'de> for LevelProbabilities {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
LevelsSeed { capacity: 0 }.deserialize(deserializer).map(Self)
}
}
impl<'de> Deserialize<'de> for Usage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(UsageVisitor)
}
}
struct UsageVisitor;
impl<'de> Visitor<'de> for UsageVisitor {
type Value = Usage;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("an object of token counts")
}
fn visit_map<M>(self, mut map: M) -> Result<Usage, M::Error>
where
M: MapAccess<'de>,
{
let (mut input_tokens, mut output_tokens) = (None, None);
while let Some(index) = map.next_key_seed(KeyIn(&["input_tokens", "output_tokens"]))? {
match index {
Some(0) => input_tokens = map.next_value()?,
Some(1) => output_tokens = map.next_value()?,
_ => {
map.next_value::<IgnoredAny>()?;
}
}
}
Ok(Usage::new(input_tokens, output_tokens))
}
}
struct Envelope<A> {
model: Name,
usage: Usage,
answers: A,
}
struct EnvelopeSeed<A> {
context: AnswerContext,
answers: PhantomData<fn() -> A>,
}
impl<A> Clone for EnvelopeSeed<A> {
fn clone(&self) -> Self {
*self
}
}
impl<A> Copy for EnvelopeSeed<A> {}
impl<'de, A> DeserializeSeed<'de> for EnvelopeSeed<A>
where
A: AnswerSet,
{
type Value = Envelope<A>;
fn deserialize<D>(self, deserializer: D) -> Result<Envelope<A>, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(self)
}
}
impl<'de, A> Visitor<'de> for EnvelopeSeed<A>
where
A: AnswerSet,
{
type Value = Envelope<A>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a System One response")
}
fn visit_map<M>(self, mut map: M) -> Result<Envelope<A>, M::Error>
where
M: MapAccess<'de>,
{
let mut model = None;
let mut usage = None;
let mut answers = None;
while let Some(index) = map.next_key_seed(KeyIn(&["model", "usage", "answers"]))? {
match index {
Some(0) => model = Some(map.next_value::<Name>()?),
Some(1) => usage = Some(map.next_value::<Usage>()?),
Some(2) => {
answers = Some(map.next_value_seed(AnswerSetSeed::<A> {
context: self.context,
answers: PhantomData,
})?);
}
_ => {
map.next_value::<IgnoredAny>()?;
}
}
}
let model = model.ok_or_else(|| de::Error::missing_field("model"))?;
let usage = usage.ok_or_else(|| de::Error::missing_field("usage"))?;
let answers = match answers {
Some(answers) => answers,
None => A::deserialize_answers(
de::value::MapDeserializer::<_, M::Error>::new(std::iter::empty::<(&str, &str)>()),
self.context,
)
.map_err(|_| de::Error::missing_field("answers"))?,
};
Ok(Envelope { model, usage, answers })
}
}
struct AnswerSetSeed<A> {
context: AnswerContext,
answers: PhantomData<A>,
}
impl<'de, A> DeserializeSeed<'de> for AnswerSetSeed<A>
where
A: AnswerSet,
{
type Value = A;
fn deserialize<D>(self, deserializer: D) -> Result<A, D::Error>
where
D: Deserializer<'de>,
{
A::deserialize_answers(deserializer, self.context)
}
}
const MIN_KEPT_ANSWER_BYTES: usize = r#""":{"type":"noul","noul":0}"#.len();
pub(crate) fn decode_system_one_with<A>(
body: Bytes,
status: StatusCode,
headers: HeaderMap,
asked: AnswerContext,
endpoint: Option<(&Method, &Uri)>,
) -> Result<SystemOneResponse<A>, Error>
where
A: AnswerSet,
{
let expected = asked.expected_answers().min(body.len() / MIN_KEPT_ANSWER_BYTES);
let context = AnswerContext { expected_answers: saturate(expected), ..asked };
let meta = ResponseMeta::new(status, headers, body);
let decoded =
codec::decode_seed(meta.raw_body(), EnvelopeSeed::<A> { context, answers: PhantomData });
match decoded {
Ok(Envelope { model, usage, answers }) => {
Ok(SystemOneResponse::from_parts(model, usage, answers, meta))
}
Err(source) => Err(invalid_response(meta, endpoint, source)),
}
}
pub(crate) fn invalid_response(
meta: ResponseMeta,
endpoint: Option<(&Method, &Uri)>,
source: DecodeError,
) -> Error {
let (status, headers, body) = meta.into_parts();
let endpoint = endpoint.map(|(method, uri)| format_endpoint(method, uri).into_boxed_str());
ResponseValidationError::new(status, body, headers, endpoint, source).into()
}
#[cfg(test)]
#[path = "de_tests.rs"]
mod tests;