|  | 
|  | 1 | +use crate::headers::from_headers::*; | 
|  | 2 | +use crate::prelude::*; | 
|  | 3 | +use crate::resources::document::DocumentAttributes; | 
|  | 4 | +use crate::ResourceQuota; | 
|  | 5 | + | 
|  | 6 | +use azure_core::headers::session_token_from_headers; | 
|  | 7 | +use azure_core::Response as HttpResponse; | 
|  | 8 | +use azure_core::SessionToken; | 
|  | 9 | +use serde::Serialize; | 
|  | 10 | +use serde_json::Value; | 
|  | 11 | +use time::OffsetDateTime; | 
|  | 12 | + | 
|  | 13 | +operation! { | 
|  | 14 | +    PatchDocument, | 
|  | 15 | +    client: DocumentClient, | 
|  | 16 | +    operations: Vec<Operation>, | 
|  | 17 | +    ?condition: String | 
|  | 18 | +} | 
|  | 19 | + | 
|  | 20 | +impl PatchDocumentBuilder { | 
|  | 21 | +    pub fn into_future(self) -> PatchDocument { | 
|  | 22 | +        Box::pin(async move { | 
|  | 23 | +            let mut request = self.client.document_request(azure_core::Method::Patch); | 
|  | 24 | + | 
|  | 25 | +            crate::cosmos_entity::add_as_partition_key_header_serialized( | 
|  | 26 | +                self.client.partition_key_serialized(), | 
|  | 27 | +                &mut request, | 
|  | 28 | +            ); | 
|  | 29 | + | 
|  | 30 | +            let patch_request = PatchDocumentRequest { | 
|  | 31 | +                condition: self.condition, | 
|  | 32 | +                operations: self.operations, | 
|  | 33 | +            }; | 
|  | 34 | + | 
|  | 35 | +            let serialized = azure_core::to_json(&patch_request)?; | 
|  | 36 | +            request.set_body(serialized); | 
|  | 37 | + | 
|  | 38 | +            let response = self | 
|  | 39 | +                .client | 
|  | 40 | +                .cosmos_client() | 
|  | 41 | +                .pipeline() | 
|  | 42 | +                .send( | 
|  | 43 | +                    self.context.clone().insert(ResourceType::Documents), | 
|  | 44 | +                    &mut request, | 
|  | 45 | +                ) | 
|  | 46 | +                .await?; | 
|  | 47 | + | 
|  | 48 | +            PatchDocumentResponse::try_from(response).await | 
|  | 49 | +        }) | 
|  | 50 | +    } | 
|  | 51 | +} | 
|  | 52 | + | 
|  | 53 | +#[derive(Serialize, Debug)] | 
|  | 54 | +struct PatchDocumentRequest { | 
|  | 55 | +    #[serde(skip_serializing_if = "Option::is_none")] | 
|  | 56 | +    condition: Option<String>, | 
|  | 57 | +    operations: Vec<Operation>, | 
|  | 58 | +} | 
|  | 59 | + | 
|  | 60 | +#[derive(Serialize, Debug, Clone)] | 
|  | 61 | +#[serde(rename_all = "lowercase")] | 
|  | 62 | +#[serde(tag = "op")] | 
|  | 63 | +pub enum Operation { | 
|  | 64 | +    Add { path: String, value: Value }, | 
|  | 65 | +    Remove { path: String }, | 
|  | 66 | +    Set { path: String, value: Value }, | 
|  | 67 | +    Incr { path: String, value: Value }, | 
|  | 68 | +    Replace { path: String, value: Value }, | 
|  | 69 | +    Move { path: String, from: String }, | 
|  | 70 | +} | 
|  | 71 | + | 
|  | 72 | +impl Operation { | 
|  | 73 | +    pub fn add<P: Into<String>, V: Serialize>( | 
|  | 74 | +        path: P, | 
|  | 75 | +        value: V, | 
|  | 76 | +    ) -> Result<Operation, serde_json::Error> { | 
|  | 77 | +        Ok(Operation::Add { | 
|  | 78 | +            path: path.into(), | 
|  | 79 | +            value: serde_json::to_value(value)?, | 
|  | 80 | +        }) | 
|  | 81 | +    } | 
|  | 82 | + | 
|  | 83 | +    pub fn remove<P: Into<String>>(path: P) -> Operation { | 
|  | 84 | +        Operation::Remove { path: path.into() } | 
|  | 85 | +    } | 
|  | 86 | + | 
|  | 87 | +    pub fn set<P: Into<String>, V: Serialize>( | 
|  | 88 | +        path: P, | 
|  | 89 | +        value: V, | 
|  | 90 | +    ) -> Result<Operation, serde_json::Error> { | 
|  | 91 | +        Ok(Operation::Set { | 
|  | 92 | +            path: path.into(), | 
|  | 93 | +            value: serde_json::to_value(value)?, | 
|  | 94 | +        }) | 
|  | 95 | +    } | 
|  | 96 | + | 
|  | 97 | +    pub fn incr<P: Into<String>, V: Serialize>( | 
|  | 98 | +        path: P, | 
|  | 99 | +        value: V, | 
|  | 100 | +    ) -> Result<Operation, serde_json::Error> { | 
|  | 101 | +        Ok(Operation::Incr { | 
|  | 102 | +            path: path.into(), | 
|  | 103 | +            value: serde_json::to_value(value)?, | 
|  | 104 | +        }) | 
|  | 105 | +    } | 
|  | 106 | + | 
|  | 107 | +    pub fn replace<P: Into<String>, V: Serialize>( | 
|  | 108 | +        path: P, | 
|  | 109 | +        value: V, | 
|  | 110 | +    ) -> Result<Operation, serde_json::Error> { | 
|  | 111 | +        Ok(Operation::Replace { | 
|  | 112 | +            path: path.into(), | 
|  | 113 | +            value: serde_json::to_value(value)?, | 
|  | 114 | +        }) | 
|  | 115 | +    } | 
|  | 116 | + | 
|  | 117 | +    pub fn r#move<P: Into<String>, F: Into<String>>(path: P, from: F) -> Operation { | 
|  | 118 | +        Operation::Move { | 
|  | 119 | +            path: path.into(), | 
|  | 120 | +            from: from.into(), | 
|  | 121 | +        } | 
|  | 122 | +    } | 
|  | 123 | +} | 
|  | 124 | + | 
|  | 125 | +#[derive(Debug, Clone)] | 
|  | 126 | +pub struct PatchDocumentResponse { | 
|  | 127 | +    pub document_attributes: DocumentAttributes, | 
|  | 128 | +    pub content_location: Option<String>, | 
|  | 129 | +    pub last_state_change: OffsetDateTime, | 
|  | 130 | +    pub resource_quota: Vec<ResourceQuota>, | 
|  | 131 | +    pub resource_usage: Vec<ResourceQuota>, | 
|  | 132 | +    pub lsn: u64, | 
|  | 133 | +    pub schema_version: String, | 
|  | 134 | +    pub alt_content_path: String, | 
|  | 135 | +    pub content_path: String, | 
|  | 136 | +    pub quorum_acked_lsn: Option<u64>, | 
|  | 137 | +    pub current_write_quorum: Option<u64>, | 
|  | 138 | +    pub current_replica_set_size: Option<u64>, | 
|  | 139 | +    pub role: u32, | 
|  | 140 | +    pub global_committed_lsn: u64, | 
|  | 141 | +    pub number_of_read_regions: u32, | 
|  | 142 | +    pub transport_request_id: u64, | 
|  | 143 | +    pub cosmos_llsn: u64, | 
|  | 144 | +    pub cosmos_quorum_acked_llsn: Option<u64>, | 
|  | 145 | +    pub session_token: SessionToken, | 
|  | 146 | +    pub charge: f64, | 
|  | 147 | +    pub service_version: String, | 
|  | 148 | +    pub activity_id: uuid::Uuid, | 
|  | 149 | +    pub gateway_version: String, | 
|  | 150 | +    pub date: OffsetDateTime, | 
|  | 151 | +} | 
|  | 152 | + | 
|  | 153 | +impl PatchDocumentResponse { | 
|  | 154 | +    pub async fn try_from(response: HttpResponse) -> azure_core::Result<Self> { | 
|  | 155 | +        let (_status_code, headers, body) = response.deconstruct(); | 
|  | 156 | +        let body = body.collect().await?; | 
|  | 157 | +        let document_attributes = serde_json::from_slice(&body)?; | 
|  | 158 | + | 
|  | 159 | +        Ok(Self { | 
|  | 160 | +            content_location: content_location_from_headers(&headers)?, | 
|  | 161 | +            last_state_change: last_state_change_from_headers(&headers)?, | 
|  | 162 | +            resource_quota: resource_quota_from_headers(&headers)?, | 
|  | 163 | +            resource_usage: resource_usage_from_headers(&headers)?, | 
|  | 164 | +            lsn: lsn_from_headers(&headers)?, | 
|  | 165 | +            schema_version: schema_version_from_headers(&headers)?, | 
|  | 166 | +            alt_content_path: alt_content_path_from_headers(&headers)?, | 
|  | 167 | +            content_path: content_path_from_headers(&headers)?, | 
|  | 168 | +            quorum_acked_lsn: quorum_acked_lsn_from_headers_optional(&headers)?, | 
|  | 169 | +            current_write_quorum: current_write_quorum_from_headers_optional(&headers)?, | 
|  | 170 | +            current_replica_set_size: current_replica_set_size_from_headers_optional(&headers)?, | 
|  | 171 | +            role: role_from_headers(&headers)?, | 
|  | 172 | +            global_committed_lsn: global_committed_lsn_from_headers(&headers)?, | 
|  | 173 | +            number_of_read_regions: number_of_read_regions_from_headers(&headers)?, | 
|  | 174 | +            transport_request_id: transport_request_id_from_headers(&headers)?, | 
|  | 175 | +            cosmos_llsn: cosmos_llsn_from_headers(&headers)?, | 
|  | 176 | +            cosmos_quorum_acked_llsn: cosmos_quorum_acked_llsn_from_headers_optional(&headers)?, | 
|  | 177 | +            session_token: session_token_from_headers(&headers)?, | 
|  | 178 | +            charge: request_charge_from_headers(&headers)?, | 
|  | 179 | +            service_version: service_version_from_headers(&headers)?, | 
|  | 180 | +            activity_id: activity_id_from_headers(&headers)?, | 
|  | 181 | +            gateway_version: gateway_version_from_headers(&headers)?, | 
|  | 182 | +            date: date_from_headers(&headers)?, | 
|  | 183 | +            document_attributes, | 
|  | 184 | +        }) | 
|  | 185 | +    } | 
|  | 186 | +} | 
0 commit comments