Skip to main content

typesafe_sdk/
de.rs

1//! Reading an answer set in one pass.
2//!
3//! The decoder walks the wire format directly instead of building a value and
4//! then interpreting it: an answer's kind is known from the member that names
5//! it, so the visitor that reads it can be chosen before its contents are
6//! parsed, and a score's integer level keys become integers without a string
7//! ever existing.
8//!
9//! The field path an error reports is built as the walk descends, which is why
10//! a failure deep in the answers can name the field it failed at rather than
11//! the object that contained it.
12//!
13//! JSON objects are unordered, so an answer's `type` may also arrive after the
14//! members it governs. Those members are then held as the raw text they
15//! arrived as - a slice of the response body, not a copy - and parsed once the
16//! type is known. Reading them eagerly instead would fail the whole response
17//! whenever an answer of a future type happened to reuse a member name with a
18//! different shape, which is exactly the answer this decoder promises to skip.
19//!
20//! [`AnswerSet`] is the seam between this walk and what the answers decode
21//! into: [`Answers`] reads them into a lookup by name, and a question set
22//! declared as a struct reads each answer straight into its field.
23
24use std::{borrow::Cow, fmt, marker::PhantomData};
25
26use bytes::Bytes;
27use http::{HeaderMap, Method, StatusCode, Uri};
28use serde::{
29    Deserialize, Deserializer,
30    de::{self, DeserializeOwned, DeserializeSeed, IgnoredAny, MapAccess, SeqAccess, Visitor},
31};
32
33use crate::{
34    codec::{self, DecodeError},
35    content::Content,
36    error::{Error, ResponseValidationError, format_endpoint},
37    name::Name,
38    response::{
39        Answer, Answers, ChoiceAnswer, NoulAnswer, ResponseMeta, ScoreAnswer, SystemOneResponse,
40        Usage, push_by_level, sort_by_level,
41    },
42};
43
44// ------------------------------------------------------------- the seam
45
46/// What the decoder knows about the answers before it reads the first one.
47///
48/// Everything in it is a hint for sizing storage. An implementation may use it
49/// or ignore it - a struct with one field per question has nothing to size -
50/// and it never changes what is decoded or whether decoding succeeds.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
52pub struct AnswerContext {
53    // Both counts are `u32`, not `usize`, saturating: they are capacity hints,
54    // and the context is carried twice in every call's future, where wider
55    // fields push that future over tokio's debug-build box size.
56    expected_answers: u32,
57    /// The most levels any score question of the request has, or 0 when
58    /// unknown: the capacity a score's level lists start at, since the codec
59    /// gives no size hint for an object.
60    levels: u32,
61}
62
63impl AnswerContext {
64    /// A context for a request that asked `expected_answers` questions.
65    pub(crate) fn new(expected_answers: usize) -> Self {
66        Self { expected_answers: saturate(expected_answers), levels: 0 }
67    }
68
69    /// The same, for a request whose largest score question has `levels`
70    /// levels, held to at most [`MAX_LEVEL_HINT`].
71    pub(crate) fn with_levels(self, levels: usize) -> Self {
72        Self { levels: saturate(levels.min(MAX_LEVEL_HINT)), ..self }
73    }
74
75    /// The level hint, as a capacity.
76    fn levels(self) -> usize {
77        self.levels as usize
78    }
79
80    /// How many questions the request asked, and so how many answers a
81    /// complete response carries, capped at the number of answers the body is
82    /// long enough to hold. Zero when unknown.
83    ///
84    /// It is a capacity hint: a response may carry fewer answers or more.
85    #[must_use]
86    pub fn expected_answers(&self) -> usize {
87        self.expected_answers as usize
88    }
89}
90
91/// The largest capacity a score's first level list starts at.
92///
93/// The hint is the largest score the request asked, but the server decides
94/// how many answers come back and how many levels each carries, so an
95/// unbounded hint lets a response multiply its size in memory. The hint
96/// exists to save the one growth a list of 5 to 8 levels pays after starting
97/// at 4, so 8 keeps all of that saving; a longer list grows from 8 as it would
98/// without a hint.
99const MAX_LEVEL_HINT: usize = 8;
100
101/// The largest capacity a choice's probability list starts at from a
102/// deserializer's size hint.
103///
104/// The answer types deserialize from any serde format, so that a caller can
105/// store answers and read them back; a self-describing binary format such as
106/// MessagePack or CBOR reports a map's declared length as its hint, and that
107/// length is chosen by the input. Trusting it would let a few bytes request
108/// an arbitrary allocation or overflow `Vec`'s capacity. A choice has a
109/// handful of options, and a longer list grows as it would without a hint,
110/// as serde's own collections do past their cap.
111const MAX_OPTION_HINT: usize = 8;
112
113/// `count` as a `u32`, or `u32::MAX` when it does not fit.
114fn saturate(count: usize) -> u32 {
115    u32::try_from(count).unwrap_or(u32::MAX)
116}
117
118/// A type the `answers` object of a response decodes into.
119///
120/// [`Answers`] implements it as a lookup by question name. A question set
121/// declared as a struct implements it by reading each answer into the field of
122/// the same name, which needs no map and no name string at all: the struct's
123/// visitor matches the key and hands the value to [`NoulAnswer`],
124/// [`ChoiceAnswer`] or [`ScoreAnswer`], whose `Deserialize` implementations
125/// are the same single-pass readers [`Answers`] uses, fixed to one kind.
126///
127/// # Contract
128///
129/// Every implementation, written by hand or generated, keeps these rules;
130/// [`Answers`] and the struct example below keep them, and the tests of this
131/// module hold both to them.
132///
133/// * **Input.** The deserializer yields exactly one JSON object, keyed by
134///   question name. Anything else (an array, a string, `null`) is an error at
135///   `answers`.
136/// * **Order.** The members of that object may arrive in any order, and inside
137///   one answer `type` may arrive after the members it governs. What a
138///   successful decode yields does not depend on either order, except which of
139///   two answers with one name is kept: the first in wire order, as the
140///   repeated-answer rule says. Which path a failure names can depend on
141///   order, as the next two rules say.
142/// * **Wrong kind.** An answer whose `type` is not the kind the field holds -
143///   including an answer that is not an object at all, or has no `type` - is
144///   an error at `answers.<field>.type` whenever `type` comes before the
145///   members of the field's kind, which is the order the API writes. A typed
146///   field knows its kind before `type` arrives and reads those members as
147///   they come, so when a misshaped member of the field's kind precedes a
148///   wrong `type`, the error is reported at that member,
149///   `answers.<field>.<member>`.
150/// * **Wrong shape.** A member of the right kind with the wrong shape is an
151///   error at `answers.<field>.<member>` when the kind is known as the member
152///   arrives: always for a typed field, and for [`Answers`] when `type` came
153///   first. [`Answers`] holds a member that arrives before `type` as raw text
154///   and checks it once the type is known, after the walk has left it, so it
155///   reports that failure at `answers.<field>`.
156/// * **Two types.** An answer that names `type` twice with two different
157///   values is an error at `answers.<field>.type`, whichever members it
158///   carries; naming the same type twice is accepted. (Upstream lets the last
159///   `type` win; an answer that contradicts itself is refused here instead.)
160/// * **Repeated answer.** When the object names one question twice, the first
161///   answer is the one the set holds. A struct keeps its field's first answer
162///   and skips a later answer of the same name unread, as it skips an extra
163///   answer, so the later one's kind and shape do not matter. [`Answers`]
164///   keeps every answer it reads, in wire order, and every lookup returns the
165///   first of them; it reads a later answer like any other, so one of the
166///   wrong shape is still an error there. A body both accept gives both the
167///   same answer.
168/// * **Missing answer.** A field with no answer is an error at
169///   `answers.<field>`, where `<field>` is the question's wire name (what
170///   `missing_field` receives), not the Rust field's identifier. A response
171///   with no `answers` member at all is an error at `answers` for every set
172///   that cannot be empty: the method is then called with an empty object,
173///   and whatever it fails with is reported as the missing member. A set that
174///   can be empty, as [`Answers`] can, decodes to its empty value.
175/// * **Extra answers.** An answer the type has no field for is skipped unread,
176///   whatever its kind or shape, and is never an error. It stays in the raw
177///   body. [`Answers`] keeps every answer of a kind this version models and
178///   skips the others the same way.
179/// * **Allocation.** Nothing is allocated beyond the storage of the fields
180///   themselves: keys are matched where they lie, never copied into a
181///   `String`, and no intermediate map or value tree is built.
182/// * **Context.** The [`AnswerContext`] is a sizing hint. An implementation may
183///   use it or ignore it, and the result is the same either way.
184///
185/// A type that does not implement the trait is refused where a response of it
186/// is asked for:
187///
188/// ```compile_fail,E0277
189/// use typesafe_sdk::de::AnswerSet;
190///
191/// fn decode_into<A: AnswerSet>() {}
192///
193/// decode_into::<String>();
194/// ```
195///
196/// An implementation for a struct of three answers looks like this. The key
197/// is matched by a field identifier whose visitor only compares the text, so
198/// a key written with escapes works and no key is copied:
199///
200/// ```
201/// use std::fmt;
202///
203/// use serde::de::{self, Deserialize, Deserializer, IgnoredAny, MapAccess, Visitor};
204/// use typesafe_sdk::{
205///     de::{AnswerContext, AnswerSet},
206///     response::{ChoiceAnswer, NoulAnswer, ScoreAnswer},
207/// };
208///
209/// struct Ticket {
210///     spam: NoulAnswer,
211///     tone: ChoiceAnswer,
212///     quality: ScoreAnswer,
213/// }
214///
215/// enum Field {
216///     Spam,
217///     Tone,
218///     Quality,
219///     Other,
220/// }
221/// # impl<'de> Deserialize<'de> for Field {
222/// #     fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
223/// #         struct FieldVisitor;
224/// #         impl Visitor<'_> for FieldVisitor {
225/// #             type Value = Field;
226/// #             fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
227/// #                 formatter.write_str("a question name")
228/// #             }
229/// #             fn visit_str<E: de::Error>(self, value: &str) -> Result<Field, E> {
230/// #                 Ok(match value {
231/// #                     "spam" => Field::Spam,
232/// #                     "tone" => Field::Tone,
233/// #                     "quality" => Field::Quality,
234/// #                     _ => Field::Other,
235/// #                 })
236/// #             }
237/// #         }
238/// #         deserializer.deserialize_str(FieldVisitor)
239/// #     }
240/// # }
241///
242/// impl AnswerSet for Ticket {
243///     fn deserialize_answers<'de, D>(deserializer: D, _: AnswerContext) -> Result<Self, D::Error>
244///     where
245///         D: Deserializer<'de>,
246///     {
247///         struct TicketVisitor;
248///
249///         impl<'de> Visitor<'de> for TicketVisitor {
250///             type Value = Ticket;
251///
252///             fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
253///                 formatter.write_str("the answers of a Ticket")
254///             }
255///
256///             fn visit_map<M>(self, mut map: M) -> Result<Ticket, M::Error>
257///             where
258///                 M: MapAccess<'de>,
259///             {
260///                 let (mut spam, mut tone, mut quality) = (None, None, None);
261///                 while let Some(field) = map.next_key::<Field>()? {
262///                     match field {
263///                         Field::Spam if spam.is_none() => spam = Some(map.next_value()?),
264///                         Field::Tone if tone.is_none() => tone = Some(map.next_value()?),
265///                         Field::Quality if quality.is_none() => {
266///                             quality = Some(map.next_value()?);
267///                         }
268///                         // An answer the struct has no field for, or a
269///                         // later answer to a question already read: the
270///                         // first answer of a name is the one kept.
271///                         _ => {
272///                             map.next_value::<IgnoredAny>()?;
273///                         }
274///                     }
275///                 }
276///                 Ok(Ticket {
277///                     spam: spam.ok_or_else(|| de::Error::missing_field("spam"))?,
278///                     tone: tone.ok_or_else(|| de::Error::missing_field("tone"))?,
279///                     quality: quality.ok_or_else(|| de::Error::missing_field("quality"))?,
280///                 })
281///             }
282///         }
283///
284///         deserializer.deserialize_map(TicketVisitor)
285///     }
286/// }
287/// ```
288#[diagnostic::on_unimplemented(
289    message = "`{Self}` cannot be decoded as the answers of a response",
290    label = "not a set of answers",
291    note = "use `Answers` to look answers up by question name, or declare a struct with one \
292            field per question and `#[derive(QuestionSet)]` it (the `macros` feature, on by \
293            default), which implements `AnswerSet`"
294)]
295pub trait AnswerSet: Sized {
296    /// Reads the `answers` object of a response.
297    ///
298    /// When a response carries no `answers` member at all, this is called with
299    /// a deserializer of an empty object. An implementation that holds
300    /// required answers fails there in the usual way, and the decoder reports
301    /// that failure as the missing `answers` member.
302    ///
303    /// # Errors
304    ///
305    /// Returns the deserializer's error when an answer is missing, is of the
306    /// wrong kind, or does not have the shape its kind requires.
307    fn deserialize_answers<'de, D>(
308        deserializer: D,
309        context: AnswerContext,
310    ) -> Result<Self, D::Error>
311    where
312        D: Deserializer<'de>;
313}
314
315impl AnswerSet for Answers {
316    fn deserialize_answers<'de, D>(
317        deserializer: D,
318        context: AnswerContext,
319    ) -> Result<Self, D::Error>
320    where
321        D: Deserializer<'de>,
322    {
323        deserializer.deserialize_map(AnswersVisitor {
324            capacity: context.expected_answers(),
325            levels: context.levels(),
326        })
327    }
328}
329
330impl<'de> Deserialize<'de> for Answers {
331    /// Reads answers with no expectation about their number. Answers of a type
332    /// this version does not model are skipped, as they are in a response.
333    ///
334    /// Reloading is supported through a JSON codec (sonic-rs, `serde_json`);
335    /// see [`ScoreAnswer`] for what a non-JSON serde format cannot read back.
336    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
337    where
338        D: Deserializer<'de>,
339    {
340        Self::deserialize_answers(deserializer, AnswerContext::default())
341    }
342}
343
344/// Reads the answers object into [`Answers`], in wire order.
345struct AnswersVisitor {
346    capacity: usize,
347    levels: usize,
348}
349
350impl<'de> Visitor<'de> for AnswersVisitor {
351    type Value = Answers;
352
353    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
354        formatter.write_str("an object of question name to answer")
355    }
356
357    fn visit_map<M>(self, mut map: M) -> Result<Answers, M::Error>
358    where
359        M: MapAccess<'de>,
360    {
361        let mut answers = Answers::with_capacity(self.capacity);
362        while let Some(name) = map.next_key_seed(TextSeed)? {
363            // The name is copied only once the answer is known to be kept, so
364            // an answer that is skipped costs no allocation for its name.
365            let seed = AnswerSeed::<Option<Answer>> {
366                name: &name,
367                levels: self.levels,
368                target: PhantomData,
369            };
370            if let Some(answer) = map.next_value_seed(seed)? {
371                answers.push(Name::from(name), answer);
372            }
373        }
374        Ok(answers)
375    }
376}
377
378// ------------------------------------------------------------ one answer
379
380/// The three answer kinds this version models.
381#[derive(Debug, Clone, Copy, PartialEq, Eq)]
382enum Kind {
383    Noul,
384    Choice,
385    Score,
386}
387
388impl Kind {
389    fn name(self) -> &'static str {
390        match self {
391            Self::Noul => "noul",
392            Self::Choice => "choice",
393            Self::Score => "score",
394        }
395    }
396}
397
398/// What an answer's `type` member said.
399enum Seen<'de> {
400    Known(Kind),
401    /// A type this version does not model, kept only to be named in a
402    /// warning. It borrows from the body unless it was written with escapes.
403    Unknown(Cow<'de, str>),
404}
405
406/// What one answer object decodes into, and how.
407///
408/// The runtime set reads any kind and skips unknown ones; the typed answers
409/// each accept exactly one kind. Both share the walk in [`AnswerSeed`] and
410/// differ only in what they build from what it collected, which is why the
411/// errors a typed field reports have the same paths as the runtime set's.
412trait Target: Sized {
413    /// The kind the answer must be, or `None` to accept any.
414    const EXPECTED: Option<Kind>;
415
416    /// Builds the value once the whole answer object has been read.
417    fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, name: &str) -> Result<Self, E>
418    where
419        E: de::Error;
420}
421
422impl Target for Option<Answer> {
423    const EXPECTED: Option<Kind> = None;
424
425    fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, name: &str) -> Result<Self, E>
426    where
427        E: de::Error,
428    {
429        match seen {
430            Some(Seen::Known(Kind::Noul)) => members.noul().map(|answer| Some(answer.into())),
431            Some(Seen::Known(Kind::Choice)) => members.choice().map(|answer| Some(answer.into())),
432            Some(Seen::Known(Kind::Score)) => members.score().map(|answer| Some(answer.into())),
433            Some(Seen::Unknown(kind)) => {
434                // Both names are the server's text - the answer's key and its
435                // `type` - so both are escaped and cut before they reach a log
436                // line; the answer's members are not logged at all.
437                #[cfg(feature = "tracing")]
438                tracing::warn!(
439                    target: crate::telemetry::TARGET,
440                    question = %crate::telemetry::ServerName(name),
441                    answer_type = %crate::telemetry::ServerName(&kind),
442                    "ignoring an answer of a type this version does not model; \
443                     the raw body still carries it"
444                );
445                #[cfg(not(feature = "tracing"))]
446                let _ = (name, kind);
447                Ok(None)
448            }
449            None => Err(E::missing_field("type")),
450        }
451    }
452}
453
454impl Target for NoulAnswer {
455    const EXPECTED: Option<Kind> = Some(Kind::Noul);
456
457    fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
458    where
459        E: de::Error,
460    {
461        match seen {
462            Some(_) => members.noul(),
463            None => Err(E::missing_field("type")),
464        }
465    }
466}
467
468impl Target for ChoiceAnswer {
469    const EXPECTED: Option<Kind> = Some(Kind::Choice);
470
471    fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
472    where
473        E: de::Error,
474    {
475        match seen {
476            Some(_) => members.choice(),
477            None => Err(E::missing_field("type")),
478        }
479    }
480}
481
482impl Target for ScoreAnswer {
483    const EXPECTED: Option<Kind> = Some(Kind::Score);
484
485    fn build<'de, E>(seen: Option<Seen<'de>>, members: Members<'de>, _: &str) -> Result<Self, E>
486    where
487        E: de::Error,
488    {
489        match seen {
490            Some(_) => members.score(),
491            None => Err(E::missing_field("type")),
492        }
493    }
494}
495
496impl<'de> Deserialize<'de> for NoulAnswer {
497    /// Reads a yes/no answer object. Its `type` must be `noul`.
498    ///
499    /// Reloading is supported through a JSON codec (sonic-rs, `serde_json`);
500    /// see [`ScoreAnswer`] for what a non-JSON serde format cannot read back.
501    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
502    where
503        D: Deserializer<'de>,
504    {
505        deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
506    }
507}
508
509impl<'de> Deserialize<'de> for ChoiceAnswer {
510    /// Reads a choice answer object. Its `type` must be `choice`.
511    ///
512    /// Reloading is supported through a JSON codec (sonic-rs, `serde_json`);
513    /// see [`ScoreAnswer`] for what a non-JSON serde format cannot read back.
514    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
515    where
516        D: Deserializer<'de>,
517    {
518        deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
519    }
520}
521
522impl<'de> Deserialize<'de> for ScoreAnswer {
523    /// Reads a score answer object. Its `type` must be `score`.
524    ///
525    /// Reloading is supported through a JSON codec (sonic-rs, `serde_json`);
526    /// see [`ScoreAnswer`] for what a non-JSON serde format cannot read back.
527    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
528    where
529        D: Deserializer<'de>,
530    {
531        deserializer.deserialize_any(AnswerSeed::<Self>::DETACHED)
532    }
533}
534
535impl<'de> Deserialize<'de> for Answer {
536    /// Reads an answer of any kind this version models. An answer of another
537    /// type is an error here: unlike a set of answers, a single answer has
538    /// nothing to fall back to.
539    ///
540    /// Reloading is supported through a JSON codec (sonic-rs, `serde_json`);
541    /// see [`ScoreAnswer`] for what a non-JSON serde format cannot read back.
542    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
543    where
544        D: Deserializer<'de>,
545    {
546        deserializer
547            .deserialize_any(AnswerSeed::<Option<Answer>>::DETACHED)?
548            .ok_or_else(|| de::Error::custom("an answer of a type this version does not model"))
549    }
550}
551
552/// Reads one answer object into `T`.
553///
554/// It is both the seed handed to the map that holds the answer and the visitor
555/// of the answer object itself.
556struct AnswerSeed<'n, T> {
557    /// The question name, for the warning an unknown type raises.
558    name: &'n str,
559    /// See [`AnswerContext`]'s field of the same name.
560    levels: usize,
561    target: PhantomData<T>,
562}
563
564impl<T> AnswerSeed<'static, T> {
565    /// A seed for an answer read on its own, outside a response: no question
566    /// name to warn with and no level hint.
567    const DETACHED: Self = Self { name: "", levels: 0, target: PhantomData };
568}
569
570impl<'de, T> DeserializeSeed<'de> for AnswerSeed<'_, T>
571where
572    T: Target,
573{
574    type Value = T;
575
576    fn deserialize<D>(self, deserializer: D) -> Result<T, D::Error>
577    where
578        D: Deserializer<'de>,
579    {
580        // `deserialize_any` rather than `deserialize_map`, so that a value
581        // that is not an object at all reaches this visitor and can be
582        // reported the way the API's own validation reports it: as an answer
583        // without a type.
584        deserializer.deserialize_any(self)
585    }
586}
587
588impl<'de, T> Visitor<'de> for AnswerSeed<'_, T>
589where
590    T: Target,
591{
592    type Value = T;
593
594    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
595        formatter.write_str("an answer object")
596    }
597
598    fn visit_map<M>(self, mut map: M) -> Result<T, M::Error>
599    where
600        M: MapAccess<'de>,
601    {
602        let mut seen: Option<Seen<'de>> = None;
603        let mut members = Members { levels: self.levels, ..Members::default() };
604
605        while let Some(index) = map.next_key_seed(Member::NAMES)? {
606            let member = match index {
607                Some(0) => {
608                    let seed = KindSeed { expected: T::EXPECTED, previous: seen.as_ref() };
609                    seen = Some(map.next_value_seed(seed)?);
610                    continue;
611                }
612                Some(at) => Member::DATA.get(at - 1).copied(),
613                None => None,
614            };
615            let Some(member) = member else {
616                map.next_value::<IgnoredAny>()?;
617                continue;
618            };
619            // How a data member is read depends on what is known of the kind
620            // at the moment it arrives. A typed answer knows its kind from the
621            // start; a runtime one learns it from `type`, and until then holds
622            // the member's raw text.
623            let known = match &seen {
624                Some(Seen::Known(kind)) => Some(*kind),
625                Some(Seen::Unknown(_)) => None,
626                None => T::EXPECTED,
627            };
628            match known {
629                Some(kind) if member.belongs_to(kind) => members.read(member, kind, &mut map)?,
630                None if seen.is_none() => members.hold(member, map.next_value_seed(RawSeed)?),
631                _ => {
632                    map.next_value::<IgnoredAny>()?;
633                }
634            }
635        }
636
637        T::build(seen, members, self.name)
638    }
639
640    fn visit_bool<E: de::Error>(self, _: bool) -> Result<T, E> {
641        Err(E::missing_field("type"))
642    }
643
644    fn visit_i64<E: de::Error>(self, _: i64) -> Result<T, E> {
645        Err(E::missing_field("type"))
646    }
647
648    fn visit_u64<E: de::Error>(self, _: u64) -> Result<T, E> {
649        Err(E::missing_field("type"))
650    }
651
652    fn visit_f64<E: de::Error>(self, _: f64) -> Result<T, E> {
653        Err(E::missing_field("type"))
654    }
655
656    fn visit_str<E: de::Error>(self, _: &str) -> Result<T, E> {
657        Err(E::missing_field("type"))
658    }
659
660    fn visit_unit<E: de::Error>(self) -> Result<T, E> {
661        Err(E::missing_field("type"))
662    }
663
664    fn visit_seq<S>(self, _: S) -> Result<T, S::Error>
665    where
666        S: SeqAccess<'de>,
667    {
668        Err(de::Error::missing_field("type"))
669    }
670}
671
672/// The data members of an answer object this version reads.
673#[derive(Debug, Clone, Copy, PartialEq, Eq)]
674enum Member {
675    Noul,
676    Choice,
677    Confidence,
678    Score,
679    Legend,
680    Probabilities,
681}
682
683impl Member {
684    /// The member names this version reads: `type` first, then the data
685    /// members in the order of [`DATA`](Member::DATA).
686    const NAMES: KeyIn =
687        KeyIn(&["type", "noul", "choice", "confidence", "score", "legend", "probabilities"]);
688    const DATA: [Self; 6] = [
689        Self::Noul,
690        Self::Choice,
691        Self::Confidence,
692        Self::Score,
693        Self::Legend,
694        Self::Probabilities,
695    ];
696
697    fn belongs_to(self, kind: Kind) -> bool {
698        match self {
699            Self::Noul => kind == Kind::Noul,
700            Self::Choice => kind == Kind::Choice,
701            Self::Confidence | Self::Probabilities => kind != Kind::Noul,
702            Self::Score | Self::Legend => kind == Kind::Score,
703        }
704    }
705}
706
707/// Reads an answer's `type`, refusing any other kind when one is expected, and
708/// any other type than the one the answer already named.
709struct KindSeed<'s, 'de> {
710    expected: Option<Kind>,
711    /// What an earlier `type` member of the same answer said, if one did.
712    previous: Option<&'s Seen<'de>>,
713}
714
715impl<'de> DeserializeSeed<'de> for KindSeed<'_, 'de> {
716    type Value = Seen<'de>;
717
718    fn deserialize<D>(self, deserializer: D) -> Result<Seen<'de>, D::Error>
719    where
720        D: Deserializer<'de>,
721    {
722        deserializer.deserialize_str(self)
723    }
724}
725
726impl<'de> KindSeed<'_, 'de> {
727    /// Classifies `text`, copying it only for a type this version does not
728    /// know, where it is kept to be named in a warning.
729    ///
730    /// A second `type` that says something else is refused here, while the
731    /// walk is on the member, so the error names `type`. Without this the last
732    /// one would win, as it does upstream, and an answer that contradicts
733    /// itself would be read as whichever kind it named last.
734    fn classify<E>(self, text: &str, keep: impl FnOnce() -> Cow<'de, str>) -> Result<Seen<'de>, E>
735    where
736        E: de::Error,
737    {
738        let seen = match text {
739            "noul" => Seen::Known(Kind::Noul),
740            "choice" => Seen::Known(Kind::Choice),
741            "score" => Seen::Known(Kind::Score),
742            _ => Seen::Unknown(keep()),
743        };
744        match (self.expected, &seen) {
745            (Some(expected), Seen::Known(kind)) if *kind != expected => {
746                return Err(wrong_kind(expected));
747            }
748            (Some(expected), Seen::Unknown(_)) => return Err(wrong_kind(expected)),
749            _ => {}
750        }
751        match self.previous {
752            Some(previous) if !previous.is_same(&seen) => Err(mixed_types()),
753            _ => Ok(seen),
754        }
755    }
756}
757
758/// The error for an answer of another kind than the one a field holds.
759fn wrong_kind<E: de::Error>(expected: Kind) -> E {
760    E::custom(format_args!("expected an answer of type `{}`", expected.name()))
761}
762
763impl Seen<'_> {
764    /// Whether two `type` members name the same type.
765    fn is_same(&self, other: &Seen<'_>) -> bool {
766        match (self, other) {
767            (Seen::Known(left), Seen::Known(right)) => left == right,
768            (Seen::Unknown(left), Seen::Unknown(right)) => left == right,
769            _ => false,
770        }
771    }
772}
773
774impl<'de> Visitor<'de> for KindSeed<'_, 'de> {
775    type Value = Seen<'de>;
776
777    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
778        formatter.write_str("an answer type name")
779    }
780
781    fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Seen<'de>, E> {
782        self.classify(value, || Cow::Borrowed(value))
783    }
784
785    fn visit_str<E: de::Error>(self, value: &str) -> Result<Seen<'de>, E> {
786        self.classify(value, || Cow::Owned(value.to_owned()))
787    }
788}
789
790// ---------------------------------------------------- collected members
791
792/// The data members of one answer object, in whatever state they arrived.
793#[derive(Default)]
794struct Members<'de> {
795    noul: Slot<'de, f64>,
796    choice: Slot<'de, Name>,
797    confidence: Slot<'de, f64>,
798    score: Slot<'de, f64>,
799    legend: Slot<'de, Vec<(u32, Content<'static>)>>,
800    probabilities: Probabilities<'de>,
801    /// The capacity a score's first level list starts at.
802    levels: usize,
803}
804
805/// One data member: absent, read, or held as raw text until the answer's type
806/// is known.
807#[derive(Default)]
808enum Slot<'de, T> {
809    #[default]
810    Missing,
811    Read(T),
812    Raw(Cow<'de, str>),
813}
814
815/// `probabilities` is keyed by option name for a choice and by level for a
816/// score, so which reading it gets depends on the kind.
817#[derive(Default)]
818enum Probabilities<'de> {
819    #[default]
820    Missing,
821    Named(Vec<(Name, f64)>),
822    Levels(Vec<(u32, f64)>),
823    Raw(Cow<'de, str>),
824}
825
826impl<'de> Members<'de> {
827    /// Reads `member` in place, as a member of an answer of `kind`.
828    fn read<M>(&mut self, member: Member, kind: Kind, map: &mut M) -> Result<(), M::Error>
829    where
830        M: MapAccess<'de>,
831    {
832        match member {
833            Member::Noul => self.noul = Slot::Read(map.next_value()?),
834            Member::Choice => self.choice = Slot::Read(map.next_value()?),
835            Member::Confidence => self.confidence = Slot::Read(map.next_value()?),
836            Member::Score => self.score = Slot::Read(map.next_value()?),
837            // A score's legend and probabilities have one entry per level, so
838            // whichever of the two arrives second is sized from the first. The
839            // first is sized from the request's level hint, never from
840            // `map.size_hint()`: that counts the answer object's remaining
841            // members, not levels, and a binary format reports whatever
842            // length its input declares, so a few bytes could ask for
843            // gigabytes.
844            Member::Legend => {
845                let capacity = match &self.probabilities {
846                    Probabilities::Levels(levels) => levels.len(),
847                    _ => self.levels,
848                };
849                self.legend = Slot::Read(map.next_value_seed(LegendSeed { capacity })?);
850            }
851            Member::Probabilities if kind == Kind::Score => {
852                let capacity = match &self.legend {
853                    Slot::Read(legend) => legend.len(),
854                    _ => self.levels,
855                };
856                self.probabilities =
857                    Probabilities::Levels(map.next_value_seed(LevelsSeed { capacity })?);
858            }
859            Member::Probabilities => {
860                self.probabilities = Probabilities::Named(map.next_value_seed(NamedSeed)?);
861            }
862        }
863        Ok(())
864    }
865
866    /// Keeps the raw text of `member` for when the type is known.
867    fn hold(&mut self, member: Member, raw: Cow<'de, str>) {
868        match member {
869            Member::Noul => self.noul = Slot::Raw(raw),
870            Member::Choice => self.choice = Slot::Raw(raw),
871            Member::Confidence => self.confidence = Slot::Raw(raw),
872            Member::Score => self.score = Slot::Raw(raw),
873            Member::Legend => self.legend = Slot::Raw(raw),
874            Member::Probabilities => self.probabilities = Probabilities::Raw(raw),
875        }
876    }
877
878    // The members are checked in the order the API schema declares them, so
879    // that an answer missing several reports the one the API's own validation
880    // would report first.
881
882    fn noul<E: de::Error>(self) -> Result<NoulAnswer, E> {
883        Ok(NoulAnswer::new(self.noul.resolve::<f64, E>("noul")?))
884    }
885
886    fn choice<E: de::Error>(self) -> Result<ChoiceAnswer, E> {
887        let choice = self.choice.resolve::<Name, E>("choice")?;
888        let confidence = self.confidence.resolve::<f64, E>("confidence")?;
889        let probabilities = match self.probabilities {
890            Probabilities::Named(named) => named,
891            Probabilities::Raw(raw) => decode_held::<NamedProbabilities, E>(&raw)?.0,
892            Probabilities::Missing => return Err(E::missing_field("probabilities")),
893            Probabilities::Levels(_) => return Err(mixed_types()),
894        };
895        Ok(ChoiceAnswer::from_parts(choice, confidence, probabilities))
896    }
897
898    fn score<E: de::Error>(self) -> Result<ScoreAnswer, E> {
899        let score = self.score.resolve::<f64, E>("score")?;
900        let confidence = self.confidence.resolve::<f64, E>("confidence")?;
901        let legend = self.legend.resolve::<Legend, E>("legend")?;
902        let probabilities = match self.probabilities {
903            Probabilities::Levels(levels) => levels,
904            Probabilities::Raw(raw) => decode_held::<LevelProbabilities, E>(&raw)?.0,
905            Probabilities::Missing => return Err(E::missing_field("probabilities")),
906            Probabilities::Named(_) => return Err(mixed_types()),
907        };
908        Ok(ScoreAnswer::from_sorted(score, confidence, legend, probabilities))
909    }
910}
911
912/// The error for an answer that names two different types.
913///
914/// [`KindSeed`] raises it at the second `type`. The two arms of the builders
915/// above that raise it too - probabilities read under one kind and built as
916/// another - cannot be reached past that check; they are there because the
917/// match over what was collected has to cover every state.
918fn mixed_types<E: de::Error>() -> E {
919    E::custom("the answer names two different types")
920}
921
922impl<T> Slot<'_, T> {
923    /// The member's value, parsing held text as `W`.
924    fn resolve<W, E>(self, member: &'static str) -> Result<T, E>
925    where
926        W: DeserializeOwned + Into<T>,
927        E: de::Error,
928    {
929        match self {
930            Self::Read(value) => Ok(value),
931            Self::Raw(raw) => decode_held::<W, E>(&raw).map(Into::into),
932            Self::Missing => Err(E::missing_field(member)),
933        }
934    }
935}
936
937/// Parses a member held as raw text.
938///
939/// The text is a complete JSON value the codec already accepted once, so the
940/// only way this fails is a value of the wrong shape. The failure is reported
941/// at the answer rather than at the member, because the walk has left the
942/// member by the time the type that says what shape it needs is known.
943fn decode_held<W, E>(raw: &str) -> Result<W, E>
944where
945    W: DeserializeOwned,
946    E: de::Error,
947{
948    codec::decode(raw.as_bytes()).map_err(E::custom)
949}
950
951/// Captures a member's value as the raw JSON text it arrived as.
952struct RawSeed;
953
954impl<'de> DeserializeSeed<'de> for RawSeed {
955    type Value = Cow<'de, str>;
956
957    fn deserialize<D>(self, deserializer: D) -> Result<Cow<'de, str>, D::Error>
958    where
959        D: Deserializer<'de>,
960    {
961        codec::deserialize_raw(deserializer)
962    }
963}
964
965// ------------------------------------------------------------ containers
966
967/// Matches an object key against a fixed list of names and yields the index
968/// of the one it is, without keeping the key's text: a key written with
969/// escapes costs nothing, and one that matches nothing is `None`.
970#[derive(Debug, Clone, Copy)]
971pub(crate) struct KeyIn(pub(crate) &'static [&'static str]);
972
973impl<'de> DeserializeSeed<'de> for KeyIn {
974    type Value = Option<usize>;
975
976    fn deserialize<D>(self, deserializer: D) -> Result<Option<usize>, D::Error>
977    where
978        D: Deserializer<'de>,
979    {
980        deserializer.deserialize_str(self)
981    }
982}
983
984impl Visitor<'_> for KeyIn {
985    type Value = Option<usize>;
986
987    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
988        formatter.write_str("an object key")
989    }
990
991    fn visit_str<E: de::Error>(self, value: &str) -> Result<Option<usize>, E> {
992        Ok(self.0.iter().position(|name| *name == value))
993    }
994}
995
996/// Reads a JSON string, borrowing it from the body when it has no escapes.
997struct TextSeed;
998
999impl<'de> DeserializeSeed<'de> for TextSeed {
1000    type Value = Cow<'de, str>;
1001
1002    fn deserialize<D>(self, deserializer: D) -> Result<Cow<'de, str>, D::Error>
1003    where
1004        D: Deserializer<'de>,
1005    {
1006        deserializer.deserialize_str(self)
1007    }
1008}
1009
1010impl<'de> Visitor<'de> for TextSeed {
1011    type Value = Cow<'de, str>;
1012
1013    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1014        formatter.write_str("a string")
1015    }
1016
1017    fn visit_borrowed_str<E: de::Error>(self, value: &'de str) -> Result<Cow<'de, str>, E> {
1018        Ok(Cow::Borrowed(value))
1019    }
1020
1021    fn visit_str<E: de::Error>(self, value: &str) -> Result<Cow<'de, str>, E> {
1022        Ok(Cow::Owned(value.to_owned()))
1023    }
1024}
1025
1026/// A score level, read straight out of the text of an object key.
1027///
1028/// The key is parsed where it lies, so no string is built for it. A codec
1029/// that hands object keys over as numbers reaches `visit_u64` instead.
1030struct LevelSeed;
1031
1032impl<'de> DeserializeSeed<'de> for LevelSeed {
1033    type Value = u32;
1034
1035    fn deserialize<D>(self, deserializer: D) -> Result<u32, D::Error>
1036    where
1037        D: Deserializer<'de>,
1038    {
1039        deserializer.deserialize_str(self)
1040    }
1041}
1042
1043impl Visitor<'_> for LevelSeed {
1044    type Value = u32;
1045
1046    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1047        formatter.write_str("a score level")
1048    }
1049
1050    fn visit_str<E: de::Error>(self, value: &str) -> Result<u32, E> {
1051        // The message does not quote the key. The key still reaches the error
1052        // as the last name of its field path, which the codec renders with
1053        // control and format characters escaped and its length capped.
1054        value.parse().map_err(|_| E::custom("a score level is a non-negative integer"))
1055    }
1056
1057    fn visit_u64<E: de::Error>(self, value: u64) -> Result<u32, E> {
1058        u32::try_from(value).map_err(|_| E::custom("a score level is a non-negative integer"))
1059    }
1060}
1061
1062/// A choice's probabilities, keyed by option name, in wire order.
1063struct NamedSeed;
1064
1065impl<'de> DeserializeSeed<'de> for NamedSeed {
1066    type Value = Vec<(Name, f64)>;
1067
1068    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1069    where
1070        D: Deserializer<'de>,
1071    {
1072        deserializer.deserialize_map(self)
1073    }
1074}
1075
1076impl<'de> Visitor<'de> for NamedSeed {
1077    type Value = Vec<(Name, f64)>;
1078
1079    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1080        formatter.write_str("an object of option name to probability")
1081    }
1082
1083    fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
1084    where
1085        M: MapAccess<'de>,
1086    {
1087        // The JSON codec gives no hint; a binary format gives the length its
1088        // input declares, which is only trusted up to a few entries.
1089        let mut entries = Vec::with_capacity(map.size_hint().unwrap_or(0).min(MAX_OPTION_HINT));
1090        while let Some(name) = map.next_key_seed(TextSeed)? {
1091            let probability = map.next_value()?;
1092            entries.push((Name::from(name), probability));
1093        }
1094        Ok(entries)
1095    }
1096}
1097
1098/// A score's probabilities, keyed by level, sorted by level.
1099struct LevelsSeed {
1100    capacity: usize,
1101}
1102
1103impl<'de> DeserializeSeed<'de> for LevelsSeed {
1104    type Value = Vec<(u32, f64)>;
1105
1106    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1107    where
1108        D: Deserializer<'de>,
1109    {
1110        deserializer.deserialize_map(self)
1111    }
1112}
1113
1114impl<'de> Visitor<'de> for LevelsSeed {
1115    type Value = Vec<(u32, f64)>;
1116
1117    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1118        formatter.write_str("an object of score level to probability")
1119    }
1120
1121    fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
1122    where
1123        M: MapAccess<'de>,
1124    {
1125        by_level(map, self.capacity, |map| map.next_value())
1126    }
1127}
1128
1129/// A score's legend, keyed by level, sorted by level.
1130struct LegendSeed {
1131    capacity: usize,
1132}
1133
1134impl<'de> DeserializeSeed<'de> for LegendSeed {
1135    type Value = Vec<(u32, Content<'static>)>;
1136
1137    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
1138    where
1139        D: Deserializer<'de>,
1140    {
1141        deserializer.deserialize_map(self)
1142    }
1143}
1144
1145impl<'de> Visitor<'de> for LegendSeed {
1146    type Value = Vec<(u32, Content<'static>)>;
1147
1148    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1149        formatter.write_str("an object of score level to description")
1150    }
1151
1152    fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
1153    where
1154        M: MapAccess<'de>,
1155    {
1156        // The description borrows the body while it is read and is copied
1157        // once, here, because a response outlives nothing it could borrow.
1158        by_level(map, self.capacity, |map| {
1159            map.next_value::<Content<'de>>().map(Content::into_owned)
1160        })
1161    }
1162}
1163
1164/// Reads an object keyed by score level into its entries, sorted by level,
1165/// each value read by `value`.
1166///
1167/// `capacity` is reserved only once a first entry exists, so an empty `{}`
1168/// allocates nothing whatever the hint. The first key is read ahead of the
1169/// loop rather than tested for inside it, which keeps the loop itself as it
1170/// is without a hint.
1171fn by_level<'de, M, V>(
1172    mut map: M,
1173    capacity: usize,
1174    mut value: impl FnMut(&mut M) -> Result<V, M::Error>,
1175) -> Result<Vec<(u32, V)>, M::Error>
1176where
1177    M: MapAccess<'de>,
1178{
1179    let Some(mut level) = map.next_key_seed(LevelSeed)? else {
1180        return Ok(Vec::new());
1181    };
1182    let mut entries = Vec::with_capacity(capacity);
1183    let mut in_order = true;
1184    loop {
1185        let read = value(&mut map)?;
1186        push_by_level(&mut entries, &mut in_order, level, read);
1187        match map.next_key_seed(LevelSeed)? {
1188            Some(next) => level = next,
1189            None => break,
1190        }
1191    }
1192    if !in_order {
1193        sort_by_level(&mut entries);
1194    }
1195    Ok(entries)
1196}
1197
1198/// The owned forms of the three containers, for a member that was held as raw
1199/// text and is parsed on its own.
1200struct Legend(Vec<(u32, Content<'static>)>);
1201struct NamedProbabilities(Vec<(Name, f64)>);
1202struct LevelProbabilities(Vec<(u32, f64)>);
1203
1204impl From<Legend> for Vec<(u32, Content<'static>)> {
1205    fn from(legend: Legend) -> Self {
1206        legend.0
1207    }
1208}
1209
1210impl<'de> Deserialize<'de> for Legend {
1211    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1212    where
1213        D: Deserializer<'de>,
1214    {
1215        LegendSeed { capacity: 0 }.deserialize(deserializer).map(Self)
1216    }
1217}
1218
1219impl<'de> Deserialize<'de> for NamedProbabilities {
1220    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1221    where
1222        D: Deserializer<'de>,
1223    {
1224        NamedSeed.deserialize(deserializer).map(Self)
1225    }
1226}
1227
1228impl<'de> Deserialize<'de> for LevelProbabilities {
1229    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1230    where
1231        D: Deserializer<'de>,
1232    {
1233        LevelsSeed { capacity: 0 }.deserialize(deserializer).map(Self)
1234    }
1235}
1236
1237// -------------------------------------------------------------- response
1238
1239impl<'de> Deserialize<'de> for Usage {
1240    /// Reads the token counts from an object. A missing or `null` count is
1241    /// `None`; members this version does not know are ignored.
1242    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1243    where
1244        D: Deserializer<'de>,
1245    {
1246        deserializer.deserialize_map(UsageVisitor)
1247    }
1248}
1249
1250/// Reads `usage` as an object only. serde's derived reader would also take a
1251/// JSON array positionally, which the API's schema does not allow.
1252struct UsageVisitor;
1253
1254impl<'de> Visitor<'de> for UsageVisitor {
1255    type Value = Usage;
1256
1257    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1258        formatter.write_str("an object of token counts")
1259    }
1260
1261    fn visit_map<M>(self, mut map: M) -> Result<Usage, M::Error>
1262    where
1263        M: MapAccess<'de>,
1264    {
1265        let (mut input_tokens, mut output_tokens) = (None, None);
1266        while let Some(index) = map.next_key_seed(KeyIn(&["input_tokens", "output_tokens"]))? {
1267            match index {
1268                Some(0) => input_tokens = map.next_value()?,
1269                Some(1) => output_tokens = map.next_value()?,
1270                _ => {
1271                    map.next_value::<IgnoredAny>()?;
1272                }
1273            }
1274        }
1275        Ok(Usage::new(input_tokens, output_tokens))
1276    }
1277}
1278
1279/// The top level of a System One response.
1280struct Envelope<A> {
1281    model: Name,
1282    usage: Usage,
1283    answers: A,
1284}
1285
1286/// Reads a System One response, handing the answer set what the decoder knows
1287/// about the answers before it reads them.
1288///
1289/// A seed rather than a `Deserialize` implementation, because the context is
1290/// per call - the number of questions this request asked - and
1291/// `Deserialize` has nowhere to receive it.
1292struct EnvelopeSeed<A> {
1293    context: AnswerContext,
1294    answers: PhantomData<fn() -> A>,
1295}
1296
1297// Written out rather than derived: a derive would ask for `A: Clone` and
1298// `A: Copy`, and the seed holds no `A` to copy.
1299impl<A> Clone for EnvelopeSeed<A> {
1300    fn clone(&self) -> Self {
1301        *self
1302    }
1303}
1304
1305impl<A> Copy for EnvelopeSeed<A> {}
1306
1307impl<'de, A> DeserializeSeed<'de> for EnvelopeSeed<A>
1308where
1309    A: AnswerSet,
1310{
1311    type Value = Envelope<A>;
1312
1313    fn deserialize<D>(self, deserializer: D) -> Result<Envelope<A>, D::Error>
1314    where
1315        D: Deserializer<'de>,
1316    {
1317        deserializer.deserialize_map(self)
1318    }
1319}
1320
1321impl<'de, A> Visitor<'de> for EnvelopeSeed<A>
1322where
1323    A: AnswerSet,
1324{
1325    type Value = Envelope<A>;
1326
1327    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
1328        formatter.write_str("a System One response")
1329    }
1330
1331    fn visit_map<M>(self, mut map: M) -> Result<Envelope<A>, M::Error>
1332    where
1333        M: MapAccess<'de>,
1334    {
1335        let mut model = None;
1336        let mut usage = None;
1337        let mut answers = None;
1338
1339        while let Some(index) = map.next_key_seed(KeyIn(&["model", "usage", "answers"]))? {
1340            match index {
1341                Some(0) => model = Some(map.next_value::<Name>()?),
1342                Some(1) => usage = Some(map.next_value::<Usage>()?),
1343                Some(2) => {
1344                    answers = Some(map.next_value_seed(AnswerSetSeed::<A> {
1345                        context: self.context,
1346                        answers: PhantomData,
1347                    })?);
1348                }
1349                _ => {
1350                    map.next_value::<IgnoredAny>()?;
1351                }
1352            }
1353        }
1354
1355        let model = model.ok_or_else(|| de::Error::missing_field("model"))?;
1356        let usage = usage.ok_or_else(|| de::Error::missing_field("usage"))?;
1357        let answers = match answers {
1358            Some(answers) => answers,
1359            // The API always sends `answers`. Without it, the answer set
1360            // decides whether "no answers" is a value it can hold: `Answers`
1361            // is then empty, as the Python SDK's default makes it. A set that
1362            // requires answers fails, and it fails at `answers` - whatever
1363            // the set would have named, the member that is not there is the
1364            // one to report, and a set of any shape reports the same path.
1365            None => A::deserialize_answers(
1366                de::value::MapDeserializer::<_, M::Error>::new(std::iter::empty::<(&str, &str)>()),
1367                self.context,
1368            )
1369            .map_err(|_| de::Error::missing_field("answers"))?,
1370        };
1371        Ok(Envelope { model, usage, answers })
1372    }
1373}
1374
1375/// Hands the `answers` member to the answer set's own reader.
1376struct AnswerSetSeed<A> {
1377    context: AnswerContext,
1378    answers: PhantomData<A>,
1379}
1380
1381impl<'de, A> DeserializeSeed<'de> for AnswerSetSeed<A>
1382where
1383    A: AnswerSet,
1384{
1385    type Value = A;
1386
1387    fn deserialize<D>(self, deserializer: D) -> Result<A, D::Error>
1388    where
1389        D: Deserializer<'de>,
1390    {
1391        A::deserialize_answers(deserializer, self.context)
1392    }
1393}
1394
1395/// The fewest bytes one answer that an answer set keeps can take in a body:
1396/// `"":{"type":"noul","noul":0}`, an empty name and the shortest answer of the
1397/// shortest kind, without even the comma that separates it from the next.
1398///
1399/// A body of `n` bytes therefore holds at most `n / MIN_KEPT_ANSWER_BYTES`
1400/// answers, which is what bounds the storage sized from a question count.
1401const MIN_KEPT_ANSWER_BYTES: usize = r#""":{"type":"noul","noul":0}"#.len();
1402
1403/// Decodes the body of a successful System One response.
1404///
1405/// `asked` carries what the request knows about its answers: the number of
1406/// questions, which sizes the answer storage once instead of growing it, and
1407/// the largest score's level count. The count is capped by how many answers
1408/// the body can hold, so no count - however large - reserves storage for
1409/// answers that cannot be there. `endpoint` names the request in the error,
1410/// and is formatted only when there is one.
1411///
1412/// # Errors
1413///
1414/// Returns [`ErrorKind::ResponseValidation`](crate::ErrorKind::ResponseValidation)
1415/// carrying the status, the headers, the whole body and the decode failure,
1416/// whose path names the field that did not fit.
1417pub(crate) fn decode_system_one_with<A>(
1418    body: Bytes,
1419    status: StatusCode,
1420    headers: HeaderMap,
1421    asked: AnswerContext,
1422    endpoint: Option<(&Method, &Uri)>,
1423) -> Result<SystemOneResponse<A>, Error>
1424where
1425    A: AnswerSet,
1426{
1427    let expected = asked.expected_answers().min(body.len() / MIN_KEPT_ANSWER_BYTES);
1428    // The level hint was bounded where it entered; only the count is capped
1429    // here.
1430    let context = AnswerContext { expected_answers: saturate(expected), ..asked };
1431    let meta = ResponseMeta::new(status, headers, body);
1432    let decoded =
1433        codec::decode_seed(meta.raw_body(), EnvelopeSeed::<A> { context, answers: PhantomData });
1434    match decoded {
1435        Ok(Envelope { model, usage, answers }) => {
1436            Ok(SystemOneResponse::from_parts(model, usage, answers, meta))
1437        }
1438        Err(source) => Err(invalid_response(meta, endpoint, source)),
1439    }
1440}
1441
1442/// The error for a success response whose body did not decode.
1443pub(crate) fn invalid_response(
1444    meta: ResponseMeta,
1445    endpoint: Option<(&Method, &Uri)>,
1446    source: DecodeError,
1447) -> Error {
1448    let (status, headers, body) = meta.into_parts();
1449    let endpoint = endpoint.map(|(method, uri)| format_endpoint(method, uri).into_boxed_str());
1450    ResponseValidationError::new(status, body, headers, endpoint, source).into()
1451}
1452
1453#[cfg(test)]
1454#[path = "de_tests.rs"]
1455mod tests;