aws_smithy_types/document/settings.rs
1/*
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6//! Protocol-specific document coercion settings.
7//!
8//! [`DocumentSettings`] is implemented by codec crates (e.g.
9//! `aws-smithy-json`, `aws-smithy-cbor`) to teach
10//! [`DiscriminatedDocument`](super::DiscriminatedDocument) how to
11//! interpret the stringly- and numerically-typed values that carry
12//! Smithy types [`Document`](super::Document) has no native variant
13//! for — most importantly base64-encoded blobs and string- or
14//! number-formatted timestamps. A protocol that follows the
15//! conventional encodings can leave every method at its default: the
16//! format-aware accessors then use deterministic defaults (standard
17//! base64 for blobs, epoch seconds for numeric timestamps, RFC-3339 for
18//! string timestamps).
19//!
20//! See the type-level docs on [`DiscriminatedDocument`](super::DiscriminatedDocument::as_blob)
21//! for how these methods feed into the `as_blob` / `as_timestamp`
22//! coercion path.
23
24use crate::{DateTime, DocumentError, Number};
25
26/// Protocol-specific settings used by
27/// [`DiscriminatedDocument`](super::DiscriminatedDocument)'s
28/// format-aware accessors.
29///
30/// Implementations live alongside the format-specific codec they apply
31/// to. For example, the JSON codec's `JsonDocumentSettings` will
32/// implement this trait to base64-decode strings into blobs and to
33/// parse timestamps according to the protocol's configured
34/// `@timestampFormat` default. A protocol whose wire format already
35/// represents blobs and timestamps natively (CBOR, Sparrowhawk) need
36/// only implement [`Self::protocol_id`] and let every coercion fall
37/// through to the default `UnsupportedOperation` body.
38///
39/// All implementations are required to be `Debug + Send + Sync` so
40/// `DiscriminatedDocument` can be cloned freely and shared across
41/// threads.
42pub trait DocumentSettings: std::fmt::Debug + Send + Sync {
43 /// The Smithy fully-qualified shape ID of the protocol that
44 /// produced this document, e.g. `"aws.protocols#restJson1"`.
45 ///
46 /// Returned as a string rather than a typed `ShapeId`: `ShapeId`
47 /// lives in `aws-smithy-schema`, which `aws-smithy-types` cannot
48 /// depend on (the dependency direction is fixed). The FQN string
49 /// is what implementations need anyway — diagnostics, error
50 /// messages, future protocol-swap dispatch.
51 fn protocol_id(&self) -> &str;
52
53 /// Coerces a string value to a blob.
54 ///
55 /// JSON-style protocols transmit blobs as base64-encoded strings
56 /// and override this method to decode. A protocol whose encoding of
57 /// a blob differs from standard base64 overrides it to say so; one
58 /// that cannot represent a blob in a string at all leaves this at
59 /// the default, which returns
60 /// [`DocumentError::UnsupportedOperation`].
61 ///
62 /// When no settings are attached at all,
63 /// [`DiscriminatedDocument::as_blob`](super::DiscriminatedDocument::as_blob)
64 /// falls back to a standard base64 decode rather than calling this
65 /// method.
66 fn coerce_string_to_blob(&self, s: &str) -> Result<Vec<u8>, DocumentError> {
67 let _ = s;
68 Err(DocumentError::unsupported(format!(
69 "protocol {} does not support coercing a string to a blob",
70 self.protocol_id()
71 )))
72 }
73
74 /// Coerces a string value to a timestamp.
75 ///
76 /// Used by protocols whose configured timestamp format encodes as a
77 /// string (e.g. `http-date`, or `date-time` when it differs from
78 /// the RFC-3339 default). Protocols that transmit timestamps only
79 /// as numbers (epoch seconds) leave this at the default.
80 fn coerce_string_to_timestamp(&self, s: &str) -> Result<DateTime, DocumentError> {
81 let _ = s;
82 Err(DocumentError::unsupported(format!(
83 "protocol {} does not support coercing a string to a timestamp",
84 self.protocol_id()
85 )))
86 }
87
88 /// Coerces a numeric value to a timestamp.
89 ///
90 /// Used by protocols whose numeric timestamp encoding differs from
91 /// plain `epoch-seconds`. Protocols that transmit timestamps only
92 /// as strings leave this at the default.
93 fn coerce_number_to_timestamp(&self, n: &Number) -> Result<DateTime, DocumentError> {
94 let _ = n;
95 Err(DocumentError::unsupported(format!(
96 "protocol {} does not support coercing a number to a timestamp",
97 self.protocol_id()
98 )))
99 }
100}