pub struct TypeRegistry { /* private fields */ }Expand description
A runtime mapping of ShapeId to RegistryEntry.
Backed by a HashMap<ShapeId<'static>, RegistryEntry>. Construct via
TypeRegistry::builder for the most common pattern, or
TypeRegistry::new/Default::default for an empty registry.
Use TypeRegistry::compose to merge two registries; entries in the
argument registry override entries with the same shape ID in self.
§Cross-lifetime lookup
Internal storage is keyed by ShapeId<'static> (codegen-emitted shapes
always have static lifetime). The public schema_for / entry_for
methods accept &ShapeId<'_> of any lifetime; lookup is by fully
qualified name via ShapeId’s Borrow<str> impl. The companion
*_fqn methods take &str directly — handy after extracting a
__type field from a wire-format JSON document.
Implementations§
Source§impl TypeRegistry
impl TypeRegistry
Sourcepub fn builder() -> TypeRegistryBuilder
pub fn builder() -> TypeRegistryBuilder
Start building a registry. See TypeRegistryBuilder.
Sourcepub fn schema_for(&self, id: &ShapeId<'_>) -> Option<&'static Schema<'static>>
pub fn schema_for(&self, id: &ShapeId<'_>) -> Option<&'static Schema<'static>>
Look up the static schema for id, or None if not registered.
Accepts a ShapeId of any lifetime — lookup is by fully
qualified name. ShapeId<'static> (codegen-emitted) and a
runtime-built ShapeId<'_> with the same FQN resolve to the
same entry.
Sourcepub fn schema_for_fqn(&self, fqn: &str) -> Option<&'static Schema<'static>>
pub fn schema_for_fqn(&self, fqn: &str) -> Option<&'static Schema<'static>>
Look up the static schema for the given fully qualified name
(e.g. "smithy.example#Bird").
Use this when you already have the FQN as a string slice — for
instance, after extracting a __type discriminator from a
JSON document.
§Example
use aws_smithy_schema::prelude;
use aws_smithy_schema::registry::TypeRegistry;
use aws_smithy_schema::serde::{SerdeError, ShapeDeserializer};
use aws_smithy_types::type_erasure::TypeErasedBox;
fn deserialize_string(d: &mut dyn ShapeDeserializer) -> Result<TypeErasedBox, SerdeError> {
Ok(TypeErasedBox::new(d.read_string(&prelude::STRING)?))
}
let registry = TypeRegistry::builder()
.insert_shape(&prelude::STRING, deserialize_string)
.build();
// FQN extracted at runtime — for instance from a wire-format
// `__type` field — looks up against the static registry.
assert!(registry.schema_for_fqn("smithy.api#String").is_some());
assert!(registry.schema_for_fqn("smithy.api#Boolean").is_none());Sourcepub fn entry_for(&self, id: &ShapeId<'_>) -> Option<&RegistryEntry>
pub fn entry_for(&self, id: &ShapeId<'_>) -> Option<&RegistryEntry>
Look up the entry (schema + deserialize fn) for id, or None
if not registered.
Accepts a ShapeId of any lifetime; see Self::schema_for.
Sourcepub fn entry_for_fqn(&self, fqn: &str) -> Option<&RegistryEntry>
pub fn entry_for_fqn(&self, fqn: &str) -> Option<&RegistryEntry>
Look up the entry for the given fully qualified name. See
Self::schema_for_fqn.
Sourcepub fn entry_for_error_code(&self, wire_code: &str) -> Option<&RegistryEntry>
pub fn entry_for_error_code(&self, wire_code: &str) -> Option<&RegistryEntry>
Look up the entry for an error shape by its wire error code
(e.g. "NotFound"), rather than by fully qualified name.
Error responses identify the error by a bare code on the wire — the
<Code> element for restXml, the __type discriminator for the JSON
protocols, the x-amzn-query-error header for awsQueryCompatible — not
by a fully qualified ShapeId. This resolves such a code to its entry
so a schema-serde error path can reify an error by the identifier it
actually receives off the wire.
wire_code is sanitized first (a leading namespace# prefix and a
trailing :url suffix are stripped), so a bare name, a fully qualified
name, or a URL-suffixed code all resolve correctly. Matching is by the
registered shape’s name; per-operation and per-service error sets are
small, so a linear scan is sufficient and needs no extra generated index.
Returns None if no registered shape’s name matches the code.
Sourcepub fn deserialize_document(
&self,
document: &DiscriminatedDocument,
) -> Result<TypeErasedBox, SerdeError>
pub fn deserialize_document( &self, document: &DiscriminatedDocument, ) -> Result<TypeErasedBox, SerdeError>
Deserialize the given document into the shape pointed to by its
discriminator.
Returns Err(SerdeError::InvalidInput { .. }) if the document has no
discriminator, and Err(SerdeError::UnknownMember { .. }) if the
discriminator does not match a registered shape.
On success, the returned [TypeErasedBox] carries an instance of the
concrete data type that the registered DeserializeFn produces.
Callers downcast via [TypeErasedBox::downcast].
The document’s lifetime is independent of the registry’s storage —
runtime-parsed documents (e.g. with a __type discriminator
borrowed from input bytes) resolve against the 'static-keyed
registry via FQN matching.
§Example
use aws_smithy_schema::prelude;
use aws_smithy_schema::registry::TypeRegistry;
use aws_smithy_schema::serde::{SerdeError, ShapeDeserializer};
use aws_smithy_types::{DiscriminatedDocument, Document};
use aws_smithy_types::type_erasure::TypeErasedBox;
fn deserialize_string(d: &mut dyn ShapeDeserializer) -> Result<TypeErasedBox, SerdeError> {
Ok(TypeErasedBox::new(d.read_string(&prelude::STRING)?))
}
let registry = TypeRegistry::builder()
.insert_shape(&prelude::STRING, deserialize_string)
.build();
// Build a discriminated document. In practice this typically comes
// from `JsonDeserializer::read_discriminated_document` after a
// wire-format `__type` lift.
let doc = DiscriminatedDocument::new(Document::String("hi".to_string()))
.with_discriminator("smithy.api#String");
let typed = registry.deserialize_document(&doc).unwrap();
let value = typed.downcast::<String>().unwrap();
assert_eq!(*value, "hi");Sourcepub fn compose(self, other: TypeRegistry) -> TypeRegistry
pub fn compose(self, other: TypeRegistry) -> TypeRegistry
Combine self and other into a new registry containing the union
of their entries.
On shape ID collision, entries from other override entries in
self. This matches the typical use case where the caller wants
extension-package entries to take precedence over base-package
entries.
Sourcepub fn or<'a>(&'a self, fallback: &'a TypeRegistry) -> ComposedRegistry<'a>
pub fn or<'a>(&'a self, fallback: &'a TypeRegistry) -> ComposedRegistry<'a>
Borrow self and fallback into a ComposedRegistry whose lookups
consult self first and fall back to fallback.
Unlike compose, this neither consumes nor copies
either registry — both are borrowed in place, so two &'static
registries (the typical case for codegen-emitted statics) can be
layered per call with no allocation.
The precedence — self wins over fallback on a colliding lookup — is
what makes this useful for operation-scoped error resolution: layer
an operation’s own error registry over the service-wide one so the
operation’s modeled errors take priority before widening to the rest of
the service closure.
Trait Implementations§
Source§impl Debug for TypeRegistry
impl Debug for TypeRegistry
Source§impl Default for TypeRegistry
impl Default for TypeRegistry
Source§fn default() -> TypeRegistry
fn default() -> TypeRegistry
Auto Trait Implementations§
impl Freeze for TypeRegistry
impl !RefUnwindSafe for TypeRegistry
impl Send for TypeRegistry
impl Sync for TypeRegistry
impl Unpin for TypeRegistry
impl UnsafeUnpin for TypeRegistry
impl !UnwindSafe for TypeRegistry
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more