| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| |
| use std::ffi::{c_char, CStr, CString}; |
| use std::time::Duration; |
| |
| use opendal::raw::PresignedRequest as ocorePresignedRequest; |
| |
| use crate::error::opendal_error; |
| use crate::operator::opendal_operator; |
| |
| /// \brief The key-value pair for the headers of the presigned request. |
| #[repr(C)] |
| #[derive(Debug)] |
| pub struct opendal_http_header_pair { |
| /// The key of the header. |
| pub key: *const c_char, |
| /// The value of the header. |
| pub value: *const c_char, |
| } |
| |
| // The internal Rust-only struct that holds the owned data. |
| #[derive(Debug)] |
| struct opendal_presigned_request_inner { |
| method: CString, |
| uri: CString, |
| headers: Vec<opendal_http_header_pair>, |
| // These vecs own the CString data for the headers |
| #[allow(dead_code)] |
| header_keys: Vec<CString>, |
| #[allow(dead_code)] |
| header_values: Vec<CString>, |
| } |
| |
| impl opendal_presigned_request_inner { |
| fn new(req: ocorePresignedRequest) -> Self { |
| let method = CString::new(req.method().as_str()).unwrap(); |
| let uri = CString::new(req.uri().to_string()).unwrap(); |
| |
| let header_keys: Vec<CString> = req |
| .header() |
| .iter() |
| .map(|(k, _)| CString::new(k.as_str()).unwrap()) |
| .collect(); |
| let header_values: Vec<CString> = req |
| .header() |
| .iter() |
| .map(|(_, v)| CString::new(v.to_str().unwrap()).unwrap()) |
| .collect(); |
| |
| let headers: Vec<opendal_http_header_pair> = header_keys |
| .iter() |
| .zip(header_values.iter()) |
| .map(|(k, v)| opendal_http_header_pair { |
| key: k.as_ptr(), |
| value: v.as_ptr(), |
| }) |
| .collect(); |
| |
| Self { |
| method, |
| uri, |
| headers, |
| header_keys, |
| header_values, |
| } |
| } |
| } |
| |
| /// \brief The underlying presigned request, which contains the HTTP method, URI, and headers. |
| /// This is an opaque struct, please use the accessor functions to get the fields. |
| #[repr(C)] |
| pub struct opendal_presigned_request { |
| inner: *mut opendal_presigned_request_inner, |
| } |
| |
| /// @brief The result of a presign operation. |
| #[repr(C)] |
| pub struct opendal_result_presign { |
| /// The presigned request. |
| pub req: *mut opendal_presigned_request, |
| /// The error. |
| pub error: *mut opendal_error, |
| } |
| |
| /// \brief Presign a read operation. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_presign_read( |
| op: &opendal_operator, |
| path: *const c_char, |
| expire_secs: u64, |
| ) -> opendal_result_presign { |
| assert!(!path.is_null()); |
| |
| let op = op.deref(); |
| let path = CStr::from_ptr(path).to_str().expect("malformed path"); |
| let duration = Duration::from_secs(expire_secs); |
| |
| match op.presign_read(path, duration) { |
| Ok(req) => { |
| let inner = Box::new(opendal_presigned_request_inner::new(req)); |
| let presigned_req = Box::new(opendal_presigned_request { |
| inner: Box::into_raw(inner), |
| }); |
| opendal_result_presign { |
| req: Box::into_raw(presigned_req), |
| error: std::ptr::null_mut(), |
| } |
| } |
| Err(e) => opendal_result_presign { |
| req: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Presign a write operation. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_presign_write( |
| op: &opendal_operator, |
| path: *const c_char, |
| expire_secs: u64, |
| ) -> opendal_result_presign { |
| assert!(!path.is_null()); |
| |
| let op = op.deref(); |
| let path = CStr::from_ptr(path).to_str().expect("malformed path"); |
| let duration = Duration::from_secs(expire_secs); |
| |
| match op.presign_write(path, duration) { |
| Ok(req) => { |
| let inner = Box::new(opendal_presigned_request_inner::new(req)); |
| let presigned_req = Box::new(opendal_presigned_request { |
| inner: Box::into_raw(inner), |
| }); |
| opendal_result_presign { |
| req: Box::into_raw(presigned_req), |
| error: std::ptr::null_mut(), |
| } |
| } |
| Err(e) => opendal_result_presign { |
| req: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Presign a delete operation. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_presign_delete( |
| op: &opendal_operator, |
| path: *const c_char, |
| expire_secs: u64, |
| ) -> opendal_result_presign { |
| assert!(!path.is_null()); |
| |
| let op = op.deref(); |
| let path = CStr::from_ptr(path).to_str().expect("malformed path"); |
| let duration = Duration::from_secs(expire_secs); |
| match op.presign_delete(path, duration) { |
| Ok(req) => { |
| let inner = Box::new(opendal_presigned_request_inner::new(req)); |
| let presigned_req = Box::new(opendal_presigned_request { |
| inner: Box::into_raw(inner), |
| }); |
| opendal_result_presign { |
| req: Box::into_raw(presigned_req), |
| error: std::ptr::null_mut(), |
| } |
| } |
| Err(e) => opendal_result_presign { |
| req: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// \brief Presign a stat operation. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_operator_presign_stat( |
| op: &opendal_operator, |
| path: *const c_char, |
| expire_secs: u64, |
| ) -> opendal_result_presign { |
| assert!(!path.is_null()); |
| |
| let op = op.deref(); |
| let path = CStr::from_ptr(path).to_str().expect("malformed path"); |
| let duration = Duration::from_secs(expire_secs); |
| |
| match op.presign_stat(path, duration) { |
| Ok(req) => { |
| let inner = Box::new(opendal_presigned_request_inner::new(req)); |
| let presigned_req = Box::new(opendal_presigned_request { |
| inner: Box::into_raw(inner), |
| }); |
| opendal_result_presign { |
| req: Box::into_raw(presigned_req), |
| error: std::ptr::null_mut(), |
| } |
| } |
| Err(e) => opendal_result_presign { |
| req: std::ptr::null_mut(), |
| error: opendal_error::new(e), |
| }, |
| } |
| } |
| |
| /// Get the method of the presigned request. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_presigned_request_method( |
| req: *const opendal_presigned_request, |
| ) -> *const c_char { |
| (*(*req).inner).method.as_ptr() |
| } |
| |
| /// Get the URI of the presigned request. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_presigned_request_uri( |
| req: *const opendal_presigned_request, |
| ) -> *const c_char { |
| (*(*req).inner).uri.as_ptr() |
| } |
| |
| /// Get the headers of the presigned request. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_presigned_request_headers( |
| req: *const opendal_presigned_request, |
| ) -> *const opendal_http_header_pair { |
| (*(*req).inner).headers.as_ptr() |
| } |
| |
| /// Get the length of the headers of the presigned request. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_presigned_request_headers_len( |
| req: *const opendal_presigned_request, |
| ) -> usize { |
| (*(*req).inner).headers.len() |
| } |
| |
| /// \brief Free the presigned request. |
| #[no_mangle] |
| pub unsafe extern "C" fn opendal_presigned_request_free(req: *mut opendal_presigned_request) { |
| if !req.is_null() { |
| // Drop the inner struct |
| drop(Box::from_raw((*req).inner)); |
| // Drop the outer struct |
| drop(Box::from_raw(req)); |
| } |
| } |