Skip to main content

aws_sdk_agentregistrycontrol/config/
endpoint.rs

1// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
2pub use ::aws_smithy_runtime_api::client::endpoint::EndpointFuture;
3pub use ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver;
4pub use ::aws_smithy_types::endpoint::Endpoint;
5
6/// Interceptor that tracks endpoint override business metric.
7#[derive(Debug, Default)]
8pub(crate) struct EndpointOverrideFeatureTrackerInterceptor;
9
10#[::aws_smithy_runtime_api::client::interceptors::dyn_dispatch_hint]
11impl ::aws_smithy_runtime_api::client::interceptors::Intercept for EndpointOverrideFeatureTrackerInterceptor {
12    fn name(&self) -> &'static str {
13        "EndpointOverrideFeatureTrackerInterceptor"
14    }
15
16    fn read_before_execution(
17        &self,
18        _context: &::aws_smithy_runtime_api::client::interceptors::context::BeforeSerializationInterceptorContextRef<'_>,
19        cfg: &mut ::aws_smithy_types::config_bag::ConfigBag,
20    ) -> ::std::result::Result<(), ::aws_smithy_runtime_api::box_error::BoxError> {
21        if cfg.load::<::aws_types::endpoint_config::EndpointUrl>().is_some() {
22            cfg.interceptor_state()
23                .store_append(::aws_runtime::sdk_feature::AwsSdkFeature::EndpointOverride);
24        }
25        ::std::result::Result::Ok(())
26    }
27}
28
29#[cfg(test)]
30mod test {
31
32    /// Region us-west-2 -> region-based prod host.
33    #[test]
34    fn test_1() {
35        let params = crate::config::endpoint::Params::builder()
36            .region("us-west-2".to_string())
37            .build()
38            .expect("invalid params");
39        let resolver = crate::config::endpoint::DefaultResolver::new();
40        let endpoint = resolver.resolve_endpoint(&params);
41        let endpoint = endpoint.expect("Expected valid endpoint: https://agent-registry-control.us-west-2.api.aws");
42        assert_eq!(
43            endpoint,
44            ::aws_smithy_types::endpoint::Endpoint::builder()
45                .url("https://agent-registry-control.us-west-2.api.aws")
46                .build()
47        );
48    }
49
50    /// Region us-east-1 -> region-based prod host.
51    #[test]
52    fn test_2() {
53        let params = crate::config::endpoint::Params::builder()
54            .region("us-east-1".to_string())
55            .build()
56            .expect("invalid params");
57        let resolver = crate::config::endpoint::DefaultResolver::new();
58        let endpoint = resolver.resolve_endpoint(&params);
59        let endpoint = endpoint.expect("Expected valid endpoint: https://agent-registry-control.us-east-1.api.aws");
60        assert_eq!(
61            endpoint,
62            ::aws_smithy_types::endpoint::Endpoint::builder()
63                .url("https://agent-registry-control.us-east-1.api.aws")
64                .build()
65        );
66    }
67
68    /// Endpoint override wins over region.
69    #[test]
70    fn test_3() {
71        let params = crate::config::endpoint::Params::builder()
72            .region("us-west-2".to_string())
73            .endpoint("https://custom.example.aws.dev".to_string())
74            .build()
75            .expect("invalid params");
76        let resolver = crate::config::endpoint::DefaultResolver::new();
77        let endpoint = resolver.resolve_endpoint(&params);
78        let endpoint = endpoint.expect("Expected valid endpoint: https://custom.example.aws.dev");
79        assert_eq!(
80            endpoint,
81            ::aws_smithy_types::endpoint::Endpoint::builder()
82                .url("https://custom.example.aws.dev")
83                .build()
84        );
85    }
86}
87
88/// Endpoint resolver trait specific to Agent Registry Control
89pub trait ResolveEndpoint: ::std::marker::Send + ::std::marker::Sync + ::std::fmt::Debug {
90    /// Resolve an endpoint with the given parameters
91    fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a>;
92
93    /// Convert this service-specific resolver into a `SharedEndpointResolver`
94    ///
95    /// The resulting resolver will downcast `EndpointResolverParams` into `crate::config::endpoint::Params`.
96    fn into_shared_resolver(self) -> ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver
97    where
98        Self: Sized + 'static,
99    {
100        ::aws_smithy_runtime_api::client::endpoint::SharedEndpointResolver::new(DowncastParams(self))
101    }
102}
103
104#[derive(Debug)]
105struct DowncastParams<T>(T);
106impl<T> ::aws_smithy_runtime_api::client::endpoint::ResolveEndpoint for DowncastParams<T>
107where
108    T: ResolveEndpoint,
109{
110    fn resolve_endpoint<'a>(
111        &'a self,
112        params: &'a ::aws_smithy_runtime_api::client::endpoint::EndpointResolverParams,
113    ) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
114        let ep = match params.get::<crate::config::endpoint::Params>() {
115            Some(params) => self.0.resolve_endpoint(params),
116            None => ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(Err("params of expected type was not present".into())),
117        };
118        ep
119    }
120}
121
122#[derive(Debug)]
123/// The default endpoint resolver.
124pub struct DefaultResolver {
125    endpoint_cache: ::arc_swap::ArcSwap<::std::option::Option<(Params, ::aws_smithy_types::endpoint::Endpoint)>>,
126}
127
128impl Default for DefaultResolver {
129    fn default() -> Self {
130        Self::new()
131    }
132}
133
134impl DefaultResolver {
135    /// Create a new DefaultResolver
136    pub fn new() -> Self {
137        Self {
138            endpoint_cache: ::arc_swap::ArcSwap::from_pointee(None),
139        }
140    }
141
142    #[allow(
143        unused_variables,
144        unused_parens,
145        clippy::double_parens,
146        clippy::useless_conversion,
147        clippy::bool_comparison,
148        clippy::comparison_to_empty,
149        clippy::needless_borrow,
150        clippy::useless_asref,
151        clippy::redundant_closure_call,
152        clippy::clone_on_copy,
153        clippy::single_char_add_str
154    )]
155    fn resolve_endpoint<'a>(
156        &'a self,
157        params: &'a crate::config::endpoint::Params,
158    ) -> ::std::result::Result<::aws_smithy_types::endpoint::Endpoint, ::aws_smithy_runtime_api::box_error::BoxError> {
159        let mut _diagnostic_collector = crate::endpoint_lib::diagnostic::DiagnosticCollector::new();
160        #[allow(unused_mut)]
161        let mut context = ConditionContext::default();
162
163        // Param bindings
164        let region = &params.region;
165        let endpoint = &params.endpoint;
166
167        let mut current_ref: i32 = 2;
168        loop {
169            match current_ref {
170                ref_val if ref_val >= 100_000_000 => {
171                    return match (ref_val - 100_000_000) as usize {
172                                        0 => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("No endpoint rule matched")) as ::aws_smithy_runtime_api::box_error::BoxError),
1731 => {
174                            let endpoint = params.endpoint.as_deref().unwrap_or_default();
175                            ::std::result::Result::Ok(::aws_smithy_types::endpoint::Endpoint::builder().url(endpoint.to_owned())
176.build())
177                        },
1782 => {
179                            let region = params.region.as_deref().unwrap_or_default();
180                            ::std::result::Result::Ok(::aws_smithy_types::endpoint::Endpoint::builder().url({ let mut out = String::new();
181out.push_str("https://agent-registry-control.");
182#[allow(clippy::needless_borrow)]
183out.push_str(&region.as_ref());
184out.push_str(".api.aws");
185out })
186.build())
187                        },
1883 => {
189
190                            ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("Unable to resolve an Agent Registry Control endpoint: Region was not set and no explicit Endpoint override was provided."
191.to_string())) as ::aws_smithy_runtime_api::box_error::BoxError)
192                        },
193                                        _ => ::std::result::Result::Err(Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("No endpoint rule matched")) as ::aws_smithy_runtime_api::box_error::BoxError),
194                                    };
195                }
196                1 | -1 => {
197                    return ::std::result::Result::Err(
198                        Box::new(::aws_smithy_http::endpoint::ResolveEndpointError::message("No endpoint rule matched"))
199                            as ::aws_smithy_runtime_api::box_error::BoxError,
200                    )
201                }
202                ref_val => {
203                    let is_complement = ref_val < 0;
204                    let node = &NODES[(ref_val.unsigned_abs() as usize) - 1];
205                    let condition_result = match node.condition_index {
206                        0 => endpoint.is_some(),
207                        1 => region.is_some(),
208                        _ => unreachable!("Invalid condition index"),
209                    };
210                    current_ref = if is_complement ^ condition_result { node.high_ref } else { node.low_ref };
211                }
212            }
213        }
214    }
215}
216
217impl crate::config::endpoint::ResolveEndpoint for DefaultResolver {
218    fn resolve_endpoint<'a>(&'a self, params: &'a crate::config::endpoint::Params) -> ::aws_smithy_runtime_api::client::endpoint::EndpointFuture<'a> {
219        // Check single-entry cache (lock-free read via ArcSwap)
220        let cached = self.endpoint_cache.load();
221        if let Some((cached_params, cached_endpoint)) = cached.as_ref() {
222            if cached_params == params {
223                return ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(::std::result::Result::Ok(cached_endpoint.clone()));
224            }
225        }
226        drop(cached);
227        let result = self.resolve_endpoint(params);
228        if let ::std::result::Result::Ok(ref endpoint) = result {
229            self.endpoint_cache.store(::std::sync::Arc::new(Some((params.clone(), endpoint.clone()))));
230        }
231        ::aws_smithy_runtime_api::client::endpoint::EndpointFuture::ready(result)
232    }
233}
234const NODES: [crate::endpoint_lib::bdd_interpreter::BddNode; 3] = [
235    crate::endpoint_lib::bdd_interpreter::BddNode {
236        condition_index: -1,
237        high_ref: 1,
238        low_ref: -1,
239    },
240    crate::endpoint_lib::bdd_interpreter::BddNode {
241        condition_index: 0,
242        high_ref: 100000001,
243        low_ref: 3,
244    },
245    crate::endpoint_lib::bdd_interpreter::BddNode {
246        condition_index: 1,
247        high_ref: 100000002,
248        low_ref: 100000003,
249    },
250];
251// These are all optional since they are set by conditions and will
252// all be unset when we start evaluation
253#[derive(Default)]
254#[allow(unused_lifetimes)]
255pub(crate) struct ConditionContext<'a> {
256    // Sometimes none of the members reference the lifetime, this makes it still valid
257    phantom: std::marker::PhantomData<&'a ()>,
258}
259
260#[non_exhaustive]
261#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::fmt::Debug)]
262/// Configuration parameters for resolving the correct endpoint
263pub struct Params {
264    /// The AWS region of the service.
265    pub(crate) region: ::std::option::Option<::std::string::String>,
266    /// Override the endpoint used to send requests.
267    pub(crate) endpoint: ::std::option::Option<::std::string::String>,
268}
269impl Params {
270    /// Create a builder for [`Params`]
271    pub fn builder() -> crate::config::endpoint::ParamsBuilder {
272        crate::config::endpoint::ParamsBuilder::default()
273    }
274    /// The AWS region of the service.
275    pub fn region(&self) -> ::std::option::Option<&str> {
276        self.region.as_deref()
277    }
278    /// Override the endpoint used to send requests.
279    pub fn endpoint(&self) -> ::std::option::Option<&str> {
280        self.endpoint.as_deref()
281    }
282}
283
284/// Builder for [`Params`]
285#[derive(::std::clone::Clone, ::std::cmp::PartialEq, ::std::default::Default, ::std::fmt::Debug)]
286pub struct ParamsBuilder {
287    region: ::std::option::Option<::std::string::String>,
288    endpoint: ::std::option::Option<::std::string::String>,
289}
290impl ParamsBuilder {
291    /// Consume this builder, creating [`Params`].
292    pub fn build(self) -> ::std::result::Result<crate::config::endpoint::Params, crate::config::endpoint::InvalidParams> {
293        if let Some(region) = &self.region {
294            if !crate::endpoint_lib::host::is_valid_host_label(
295                region.as_ref() as &str,
296                true,
297                &mut crate::endpoint_lib::diagnostic::DiagnosticCollector::new(),
298            ) {
299                return Err(crate::config::endpoint::InvalidParams::invalid_value(
300                    "region",
301                    "must be a valid host label",
302                ));
303            }
304        };
305        Ok(
306            #[allow(clippy::unnecessary_lazy_evaluations)]
307            crate::config::endpoint::Params {
308                region: self.region,
309                endpoint: self.endpoint,
310            },
311        )
312    }
313    /// Sets the value for region
314    ///
315    /// The AWS region of the service.
316    pub fn region(mut self, value: impl Into<::std::string::String>) -> Self {
317        self.region = Some(value.into());
318        self
319    }
320
321    /// Sets the value for region
322    ///
323    /// The AWS region of the service.
324    pub fn set_region(mut self, param: Option<::std::string::String>) -> Self {
325        self.region = param;
326        self
327    }
328    /// Sets the value for endpoint
329    ///
330    /// Override the endpoint used to send requests.
331    pub fn endpoint(mut self, value: impl Into<::std::string::String>) -> Self {
332        self.endpoint = Some(value.into());
333        self
334    }
335
336    /// Sets the value for endpoint
337    ///
338    /// Override the endpoint used to send requests.
339    pub fn set_endpoint(mut self, param: Option<::std::string::String>) -> Self {
340        self.endpoint = param;
341        self
342    }
343}
344
345/// An error that occurred during endpoint resolution
346#[derive(Debug)]
347pub struct InvalidParams {
348    field: std::borrow::Cow<'static, str>,
349    kind: InvalidParamsErrorKind,
350}
351
352/// The kind of invalid parameter error
353#[derive(Debug)]
354enum InvalidParamsErrorKind {
355    MissingField,
356    InvalidValue { message: &'static str },
357}
358
359impl InvalidParams {
360    #[allow(dead_code)]
361    fn missing(field: &'static str) -> Self {
362        Self {
363            field: field.into(),
364            kind: InvalidParamsErrorKind::MissingField,
365        }
366    }
367
368    #[allow(dead_code)]
369    fn invalid_value(field: &'static str, message: &'static str) -> Self {
370        Self {
371            field: field.into(),
372            kind: InvalidParamsErrorKind::InvalidValue { message },
373        }
374    }
375}
376
377impl std::fmt::Display for InvalidParams {
378    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379        match self.kind {
380            InvalidParamsErrorKind::MissingField => write!(f, "a required field was missing: `{}`", self.field),
381            InvalidParamsErrorKind::InvalidValue { message } => write!(f, "invalid value for field: `{}` - {}", self.field, message),
382        }
383    }
384}
385
386impl std::error::Error for InvalidParams {}