Skip to main content

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}