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;