Skip to main content

prepared_request/
prepared_request.rs

1//! Prepares a complete provider-neutral operation without performing I/O.
2
3use cloud_sdk::operation::{
4    ContentTypePolicy, CostIntent, OperationImpact, OperationMetadata, PreparationStorage,
5    PrepareOperation, PreparedRequest, ProviderService, RequestSemantics, ResponseBodyPolicy,
6    ResponsePolicy, RetryEligibility,
7};
8use cloud_sdk::transport::{
9    EndpointIdentity, EndpointScheme, MediaType, RequestTarget, StatusCode,
10};
11use cloud_sdk::transport::{MAX_REQUEST_TARGET_BYTES, TransportRequest};
12use cloud_sdk::{ApiFamily, Method, Provider};
13
14static OK_STATUS: [StatusCode; 1] = [StatusCode::OK];
15static JSON_MEDIA: [MediaType<'static>; 1] = [MediaType::JSON];
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq)]
18enum PrepareError {
19    TargetBuffer,
20    InvalidTarget,
21    InvalidMetadata,
22    InvalidResponsePolicy,
23    InvalidEndpoint,
24}
25
26struct ListResources;
27
28impl PrepareOperation for ListResources {
29    type Error = PrepareError;
30
31    fn prepare<'storage>(
32        &self,
33        storage: PreparationStorage<'storage>,
34    ) -> Result<PreparedRequest<'storage>, Self::Error> {
35        let (target_storage, _body_storage) = storage.into_parts();
36        let target = target_storage
37            .get_mut(..17)
38            .ok_or(PrepareError::TargetBuffer)?;
39        target.copy_from_slice(b"/resources?page=1");
40        let target = core::str::from_utf8(target).map_err(|_| PrepareError::InvalidTarget)?;
41        let target = RequestTarget::new(target).map_err(|_| PrepareError::InvalidTarget)?;
42        let request = TransportRequest::new(Method::Get, target);
43        let metadata = OperationMetadata::new(
44            OperationImpact::ReadOnly,
45            RequestSemantics::Safe,
46            RetryEligibility::ExplicitPolicy,
47            CostIntent::NoKnownCost,
48        )
49        .map_err(|_| PrepareError::InvalidMetadata)?;
50        let response_policy = ResponsePolicy::new(
51            &OK_STATUS,
52            ContentTypePolicy::Required(&JSON_MEDIA),
53            ResponseBodyPolicy::Required,
54            65_536,
55        )
56        .map_err(|_| PrepareError::InvalidResponsePolicy)?;
57        let endpoint =
58            EndpointIdentity::new(EndpointScheme::Https, "api.example.invalid", 443, "/v1")
59                .map_err(|_| PrepareError::InvalidEndpoint)?;
60        Ok(PreparedRequest::new(
61            request,
62            ProviderService::new(Provider::Hetzner, ApiFamily::Cloud, endpoint),
63            metadata,
64            response_policy,
65        ))
66    }
67}
68
69fn main() {
70    let mut target = [0_u8; MAX_REQUEST_TARGET_BYTES];
71    let mut body = [0_u8; 1];
72    let prepared = ListResources.prepare(PreparationStorage::new(&mut target, &mut body));
73    let Ok(prepared) = prepared else { return };
74
75    assert_eq!(prepared.transport_request().method(), Method::Get);
76    assert_eq!(prepared.metadata().impact(), OperationImpact::ReadOnly);
77    assert_eq!(prepared.response_policy().max_body_bytes(), 65_536);
78}