| /* |
| * 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. |
| */ |
| |
| #include <chrono> |
| #include <cstdio> |
| #include <ctime> |
| |
| #include "lib.rs.h" |
| #include "opendal.hpp" |
| #include "utils/ffi_converter.hpp" |
| #include "utils/rust_converter.hpp" |
| |
| namespace opendal { |
| |
| std::optional<std::string> parse_optional_string(ffi::OptionalString &&s) { |
| if (s.has_value) { |
| return std::string(std::move(s.value)); |
| } else { |
| return std::nullopt; |
| } |
| } |
| |
| std::optional<bool> parse_optional_bool(ffi::OptionalBool &&b) { |
| if (b.has_value) { |
| return b.value; |
| } else { |
| return std::nullopt; |
| } |
| } |
| |
| Metadata parse_meta_data(ffi::Metadata &&meta) { |
| Metadata metadata; |
| |
| // Basic information |
| metadata.type = static_cast<EntryMode>(meta.mode); |
| metadata.content_length = meta.content_length; |
| |
| // HTTP-style headers |
| metadata.cache_control = parse_optional_string(std::move(meta.cache_control)); |
| metadata.content_disposition = |
| parse_optional_string(std::move(meta.content_disposition)); |
| metadata.content_md5 = parse_optional_string(std::move(meta.content_md5)); |
| metadata.content_type = parse_optional_string(std::move(meta.content_type)); |
| metadata.content_encoding = |
| parse_optional_string(std::move(meta.content_encoding)); |
| metadata.etag = parse_optional_string(std::move(meta.etag)); |
| |
| // Versioning information |
| metadata.version = parse_optional_string(std::move(meta.version)); |
| metadata.is_current = parse_optional_bool(std::move(meta.is_current)); |
| metadata.is_deleted = meta.is_deleted; |
| |
| // Parse last_modified timestamp |
| auto last_modified_str = parse_optional_string(std::move(meta.last_modified)); |
| if (last_modified_str.has_value()) { |
| // Parse ISO 8601 string to time_point using strptime to avoid locale lock |
| std::tm tm = {}; |
| const char *str = last_modified_str.value().c_str(); |
| |
| // Parse ISO 8601 format: YYYY-MM-DDTHH:MM:SS |
| int year, month, day, hour, minute, second; |
| if (sscanf(str, "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, |
| &second) == 6) { |
| tm.tm_year = year - 1900; // years since 1900 |
| tm.tm_mon = month - 1; // months since January (0-11) |
| tm.tm_mday = day; |
| tm.tm_hour = hour; |
| tm.tm_min = minute; |
| tm.tm_sec = second; |
| tm.tm_isdst = -1; // let mktime determine DST |
| |
| std::time_t time_t_value = std::mktime(&tm); |
| if (time_t_value != -1) { |
| metadata.last_modified = |
| std::chrono::system_clock::from_time_t(time_t_value); |
| } |
| } |
| } |
| |
| return metadata; |
| } |
| |
| Operator::Operator() noexcept = default; |
| |
| void Operator::Destroy() noexcept { |
| if (operator_) { |
| ffi::delete_operator(operator_); |
| operator_ = nullptr; |
| } |
| } |
| |
| Operator::Operator(std::string_view scheme, |
| const std::unordered_map<std::string, std::string> &config) { |
| auto rust_map = rust::Vec<ffi::HashMapValue>(); |
| rust_map.reserve(config.size()); |
| |
| for (auto &[k, v] : config) { |
| rust_map.push_back({utils::rust_string(k), utils::rust_string(v)}); |
| } |
| |
| operator_ = ffi::new_operator(utils::rust_str(scheme), rust_map); |
| } |
| |
| Operator::~Operator() noexcept { Destroy(); } |
| |
| Operator::Operator(Operator &&other) noexcept : operator_(other.operator_) { |
| other.operator_ = nullptr; |
| } |
| |
| Operator &Operator::operator=(Operator &&other) noexcept { |
| if (this != &other) { |
| Destroy(); |
| |
| operator_ = other.operator_; |
| other.operator_ = nullptr; |
| } |
| |
| return *this; |
| } |
| |
| bool Operator::Available() const { return operator_ != nullptr; } |
| |
| // We can't avoid copy, because std::vector hides the internal structure. |
| // std::vector doesn't support init from a pointer without copy. |
| std::string Operator::Read(std::string_view path) { |
| auto rust_vec = operator_->read(utils::rust_str(path)); |
| return {rust_vec.begin(), rust_vec.end()}; |
| } |
| |
| void Operator::Write(std::string_view path, std::string_view data) { |
| rust::Vec<uint8_t> vec; |
| std::copy(data.begin(), data.end(), std::back_inserter(vec)); |
| operator_->write(utils::rust_str(path), vec); |
| } |
| |
| bool Operator::Exists(std::string_view path) { |
| return operator_->exists(utils::rust_str(path)); |
| } |
| |
| bool Operator::IsExist(std::string_view path) { return Exists(path); } |
| |
| void Operator::CreateDir(std::string_view path) { |
| operator_->create_dir(utils::rust_str(path)); |
| } |
| |
| void Operator::Copy(std::string_view src, std::string_view dst) { |
| operator_->copy(utils::rust_str(src), utils::rust_str(dst)); |
| } |
| |
| void Operator::Rename(std::string_view src, std::string_view dst) { |
| operator_->rename(utils::rust_str(src), utils::rust_str(dst)); |
| } |
| |
| void Operator::Remove(std::string_view path) { |
| operator_->remove(utils::rust_str(path)); |
| } |
| |
| Metadata Operator::Stat(std::string_view path) { |
| return parse_meta_data(operator_->stat(utils::rust_str(path))); |
| } |
| |
| std::vector<Entry> Operator::List(std::string_view path) { |
| auto rust_vec = operator_->list(utils::rust_str(path)); |
| |
| std::vector<Entry> entries; |
| entries.reserve(rust_vec.size()); |
| for (auto &&entry : rust_vec) { |
| entries.emplace_back(utils::parse_entry(std::move(entry))); |
| } |
| |
| return entries; |
| } |
| |
| Lister Operator::GetLister(std::string_view path) { |
| return operator_->lister(utils::rust_str(path)); |
| } |
| |
| Reader Operator::GetReader(std::string_view path) { |
| return operator_->reader(utils::rust_str(path)); |
| } |
| |
| } // namespace opendal |
| opendal::Capability opendal::Operator::Info() { |
| auto op_info = operator_->info(); |
| return Capability{ |
| .stat = op_info.stat, |
| .stat_with_if_match = op_info.stat_with_if_match, |
| .stat_with_if_none_match = op_info.stat_with_if_none_match, |
| .read = op_info.read, |
| .read_with_if_match = op_info.read_with_if_match, |
| .read_with_if_none_match = op_info.read_with_if_none_match, |
| .read_with_override_cache_control = op_info.read_with_override_cache_control, |
| .read_with_override_content_disposition = |
| op_info.read_with_override_content_disposition, |
| .read_with_override_content_type = op_info.read_with_override_content_type, |
| .write = op_info.write, |
| .write_can_multi = op_info.write_can_multi, |
| .write_can_empty = op_info.write_can_empty, |
| .write_can_append = op_info.write_can_append, |
| .write_with_content_type = op_info.write_with_content_type, |
| .write_with_content_disposition = op_info.write_with_content_disposition, |
| .write_with_cache_control = op_info.write_with_cache_control, |
| .write_multi_max_size = op_info.write_multi_max_size, |
| .write_multi_min_size = op_info.write_multi_min_size, |
| .write_total_max_size = op_info.write_total_max_size, |
| .create_dir = op_info.create_dir, |
| .delete_feature = op_info.delete_feature, |
| .copy = op_info.copy, |
| .rename = op_info.rename, |
| .list = op_info.list, |
| .list_with_limit = op_info.list_with_limit, |
| .list_with_start_after = op_info.list_with_start_after, |
| .list_with_recursive = op_info.list_with_recursive, |
| .presign = op_info.presign, |
| .presign_read = op_info.presign_read, |
| .presign_stat = op_info.presign_stat, |
| .presign_write = op_info.presign_write, |
| .shared = op_info.shared, |
| }; |
| } |