74 :
work_(std::move(work)) {}
92 std::shared_ptr<async_state<T>>
state_;
112 std::thread([state, handle]()
mutable {
114 state->result_.emplace(state->work_());
116 state->exception_ = std::current_exception();
120 state->ready_.store(
true, std::memory_order_release);
129 while (!
state_->ready_.load(std::memory_order_acquire)) {
134 std::rethrow_exception(
state_->exception_);
136 return std::move(*
state_->result_);
143 using result_type = std::invoke_result_t<F>;
180 :
container_(std::make_shared<value_container>())
207 [[nodiscard]] std::shared_ptr<value_container>
get_container() const noexcept
244#if CONTAINER_HAS_COMMON_RESULT
255#if CONTAINER_HAS_COMMON_RESULT
282#if CONTAINER_HAS_COMMON_RESULT
296#if CONTAINER_HAS_COMMON_RESULT
329 [[nodiscard]] std::optional<T>
get(std::string_view key)
const
335 if (
auto* ptr = std::get_if<T>(&val->data)) {
346 [[nodiscard]]
bool contains(std::string_view key)
const noexcept
373#if CONTAINER_HAS_COMMON_RESULT
375 std::string_view path,
379 std::string_view path,
401#if CONTAINER_HAS_COMMON_RESULT
403 std::string_view path,
407 std::string_view path,
433 size_t chunk_size = 64 * 1024)
const;
458#if CONTAINER_HAS_COMMON_RESULT
461 std::span<const uint8_t> data,
462 bool is_final =
true);
466 std::span<const uint8_t> data,
467 bool is_final =
true);
495#if CONTAINER_HAS_COMMON_RESULT
497 std::string_view path,
501 std::string_view path,
523#if CONTAINER_HAS_COMMON_RESULT
525 std::string_view path,
526 std::span<const uint8_t> data,
530 std::string_view path,
531 std::span<const uint8_t> data,
539#if CONTAINER_HAS_COMMON_RESULT
545 return container->serialize(value_container::serialization_format::binary);
550 inline task<kcenon::common::Result<std::string>>
555 return container->serialize_string(value_container::serialization_format::binary);
560 inline task<kcenon::common::Result<std::shared_ptr<value_container>>>
563 std::vector<uint8_t> data_copy(data.begin(), data.end());
565 [data_copy = std::move(data_copy)]() {
566 auto container = std::make_shared<value_container>();
567 auto deser_result = container->deserialize_result(data_copy,
false);
568 if (!deser_result.is_ok()) {
569 return kcenon::common::Result<std::shared_ptr<value_container>>(
570 deser_result.error());
572 return kcenon::common::ok(container);
577 inline task<kcenon::common::Result<std::shared_ptr<value_container>>>
580 std::string data_copy(data);
582 [data_copy = std::move(data_copy)]() {
583 auto container = std::make_shared<value_container>();
584 auto deser_result = container->deserialize_result(data_copy,
false);
585 if (!deser_result.is_ok()) {
586 return kcenon::common::Result<std::shared_ptr<value_container>>(
587 deser_result.error());
589 return kcenon::common::ok(container);
594 inline task<kcenon::common::VoidResult>
599 std::string path_str(path);
601 [container, path_str, callback]() -> kcenon::common::VoidResult {
602 std::ifstream file(path_str, std::ios::binary | std::ios::ate);
604 return kcenon::common::VoidResult(
605 kcenon::common::error_info{
606 kcenon::container::error_codes::file_not_found,
607 kcenon::container::error_codes::make_message(
608 kcenon::container::error_codes::file_not_found, path_str),
609 "container_system"});
612 auto size = file.tellg();
614 return kcenon::common::VoidResult(
615 kcenon::common::error_info{
616 kcenon::container::error_codes::file_read_error,
617 kcenon::container::error_codes::make_message(
618 kcenon::container::error_codes::file_read_error, path_str),
619 "container_system"});
621 file.seekg(0, std::ios::beg);
623 std::vector<uint8_t> buffer(
static_cast<size_t>(size));
624 const size_t chunk_size = 64 * 1024;
625 size_t bytes_read = 0;
627 while (bytes_read <
static_cast<size_t>(size)) {
628 size_t to_read = std::min(chunk_size,
629 static_cast<size_t>(size) - bytes_read);
630 file.read(
reinterpret_cast<char*
>(buffer.data() + bytes_read),
631 static_cast<std::streamsize
>(to_read));
633 return kcenon::common::VoidResult(
634 kcenon::common::error_info{
635 kcenon::container::error_codes::file_read_error,
636 kcenon::container::error_codes::make_message(
637 kcenon::container::error_codes::file_read_error, path_str),
638 "container_system"});
640 bytes_read += to_read;
642 callback(bytes_read,
static_cast<size_t>(size));
646 auto deser_result = container->deserialize_result(buffer,
false);
647 if (!deser_result.is_ok()) {
650 return kcenon::common::ok();
655 inline task<kcenon::common::VoidResult>
659 std::string path_str(path);
661 [container, path_str, callback]() -> kcenon::common::VoidResult {
662 auto data_result = container->serialize(value_container::serialization_format::binary);
663 if (!data_result.is_ok()) {
664 return kcenon::common::VoidResult(data_result.error());
666 const auto& data = data_result.value();
668 std::ofstream file(path_str, std::ios::binary);
670 return kcenon::common::VoidResult(
671 kcenon::common::error_info{
672 kcenon::container::error_codes::file_write_error,
673 kcenon::container::error_codes::make_message(
674 kcenon::container::error_codes::file_write_error, path_str),
675 "container_system"});
678 const size_t chunk_size = 64 * 1024;
679 size_t bytes_written = 0;
680 const size_t total_size = data.size();
682 while (bytes_written < total_size) {
683 size_t to_write = std::min(chunk_size, total_size - bytes_written);
684 file.write(
reinterpret_cast<const char*
>(data.data() + bytes_written),
685 static_cast<std::streamsize
>(to_write));
687 return kcenon::common::VoidResult(
688 kcenon::common::error_info{
689 kcenon::container::error_codes::file_write_error,
690 kcenon::container::error_codes::make_message(
691 kcenon::container::error_codes::file_write_error, path_str),
692 "container_system"});
694 bytes_written += to_write;
696 callback(bytes_written, total_size);
700 return kcenon::common::ok();
705 inline task<kcenon::common::Result<std::vector<uint8_t>>>
708 std::string path_str(path);
710 [path_str, callback]() -> kcenon::common::Result<std::vector<uint8_t>> {
711 std::ifstream file(path_str, std::ios::binary | std::ios::ate);
713 return kcenon::common::Result<std::vector<uint8_t>>(
714 kcenon::common::error_info{
715 kcenon::container::error_codes::file_not_found,
716 kcenon::container::error_codes::make_message(
717 kcenon::container::error_codes::file_not_found, path_str),
718 "container_system"});
721 auto size = file.tellg();
723 return kcenon::common::Result<std::vector<uint8_t>>(
724 kcenon::common::error_info{
725 kcenon::container::error_codes::file_read_error,
726 kcenon::container::error_codes::make_message(
727 kcenon::container::error_codes::file_read_error, path_str),
728 "container_system"});
730 file.seekg(0, std::ios::beg);
732 std::vector<uint8_t> buffer(
static_cast<size_t>(size));
733 const size_t chunk_size = 64 * 1024;
734 size_t bytes_read = 0;
736 while (bytes_read <
static_cast<size_t>(size)) {
737 size_t to_read = std::min(chunk_size,
738 static_cast<size_t>(size) - bytes_read);
739 file.read(
reinterpret_cast<char*
>(buffer.data() + bytes_read),
740 static_cast<std::streamsize
>(to_read));
742 return kcenon::common::Result<std::vector<uint8_t>>(
743 kcenon::common::error_info{
744 kcenon::container::error_codes::file_read_error,
745 kcenon::container::error_codes::make_message(
746 kcenon::container::error_codes::file_read_error, path_str),
747 "container_system"});
749 bytes_read += to_read;
751 callback(bytes_read,
static_cast<size_t>(size));
755 return kcenon::common::ok(std::move(buffer));
760 inline task<kcenon::common::VoidResult>
764 std::string path_str(path);
765 std::vector<uint8_t> data_copy(data.begin(), data.end());
767 [path_str, data_copy = std::move(data_copy), callback]()
768 -> kcenon::common::VoidResult {
769 std::ofstream file(path_str, std::ios::binary);
771 return kcenon::common::VoidResult(
772 kcenon::common::error_info{
773 kcenon::container::error_codes::file_write_error,
774 kcenon::container::error_codes::make_message(
775 kcenon::container::error_codes::file_write_error, path_str),
776 "container_system"});
779 const size_t chunk_size = 64 * 1024;
780 size_t bytes_written = 0;
781 const size_t total_size = data_copy.size();
783 while (bytes_written < total_size) {
784 size_t to_write = std::min(chunk_size, total_size - bytes_written);
785 file.write(
reinterpret_cast<const char*
>(data_copy.data() + bytes_written),
786 static_cast<std::streamsize
>(to_write));
788 return kcenon::common::VoidResult(
789 kcenon::common::error_info{
790 kcenon::container::error_codes::file_write_error,
791 kcenon::container::error_codes::make_message(
792 kcenon::container::error_codes::file_write_error, path_str),
793 "container_system"});
795 bytes_written += to_write;
797 callback(bytes_written, total_size);
801 return kcenon::common::ok();
810 inline generator<std::vector<uint8_t>>
813 auto data_result =
container_->serialize(value_container::serialization_format::binary);
814 if (!data_result.is_ok()) {
818 const auto& full_data = data_result.value();
819 const size_t total_size = full_data.size();
822 while (offset < total_size) {
823 size_t current_chunk_size = std::min(chunk_size, total_size - offset);
824 std::vector<uint8_t> chunk(
825 full_data.begin() +
static_cast<std::ptrdiff_t
>(offset),
826 full_data.begin() +
static_cast<std::ptrdiff_t
>(offset + current_chunk_size));
827 offset += current_chunk_size;
832 inline task<kcenon::common::Result<std::shared_ptr<value_container>>>
834 std::span<const uint8_t> data,
843 co_return kcenon::common::Result<std::shared_ptr<value_container>>(
844 kcenon::common::error_info{
845 kcenon::container::error_codes::deserialization_failed,
846 kcenon::container::error_codes::make_message(
847 kcenon::container::error_codes::deserialization_failed,
848 "streaming requires complete data (is_final=true)"),
849 "container_system"});
852 std::vector<uint8_t> data_copy(data.begin(), data.end());
854 [data_copy = std::move(data_copy)]() {
855 auto container = std::make_shared<value_container>();
856 auto deser_result = container->deserialize_result(data_copy,
false);
857 if (!deser_result.is_ok()) {
858 return kcenon::common::Result<std::shared_ptr<value_container>>(
859 deser_result.error());
861 return kcenon::common::ok(container);
868 inline task<std::vector<uint8_t>>
873 auto serialize_result = container->serialize(serialization_format::binary);
874 return serialize_result.is_ok() ? serialize_result.value() : std::vector<uint8_t>{};
884 auto serialize_result = container->serialize_string(serialization_format::binary);
885 return serialize_result.is_ok() ? serialize_result.value() : std::string{};
893 std::vector<uint8_t> data_copy(data.begin(), data.end());
895 [data_copy = std::move(data_copy)]() {
896 auto container = std::make_shared<value_container>(data_copy,
false);
905 std::string data_copy(data);
907 [data_copy = std::move(data_copy)]() {
908 auto container = std::make_shared<value_container>(data_copy,
false);
918 std::string path_str(path);
920 [container, path_str, callback]() {
921 std::ifstream file(path_str, std::ios::binary | std::ios::ate);
926 auto size = file.tellg();
930 file.seekg(0, std::ios::beg);
932 std::vector<uint8_t> buffer(
static_cast<size_t>(size));
933 const size_t chunk_size = 64 * 1024;
934 size_t bytes_read = 0;
936 while (bytes_read <
static_cast<size_t>(size)) {
937 size_t to_read = std::min(chunk_size,
938 static_cast<size_t>(size) - bytes_read);
939 file.read(
reinterpret_cast<char*
>(buffer.data() + bytes_read),
940 static_cast<std::streamsize
>(to_read));
944 bytes_read += to_read;
946 callback(bytes_read,
static_cast<size_t>(size));
950 container->deserialize(buffer,
false);
960 std::string path_str(path);
962 [container, path_str, callback]() {
963 auto serialize_result = container->serialize(serialization_format::binary);
964 if (!serialize_result.is_ok()) {
967 auto data = serialize_result.value();
972 std::ofstream file(path_str, std::ios::binary);
977 const size_t chunk_size = 64 * 1024;
978 size_t bytes_written = 0;
979 const size_t total_size = data.size();
981 while (bytes_written < total_size) {
982 size_t to_write = std::min(chunk_size, total_size - bytes_written);
983 file.write(
reinterpret_cast<const char*
>(data.data() + bytes_written),
984 static_cast<std::streamsize
>(to_write));
988 bytes_written += to_write;
990 callback(bytes_written, total_size);
1002 std::string path_str(path);
1004 [path_str, callback]() {
1005 std::ifstream file(path_str, std::ios::binary | std::ios::ate);
1007 return std::vector<uint8_t>{};
1010 auto size = file.tellg();
1012 return std::vector<uint8_t>{};
1014 file.seekg(0, std::ios::beg);
1016 std::vector<uint8_t> buffer(
static_cast<size_t>(size));
1017 const size_t chunk_size = 64 * 1024;
1018 size_t bytes_read = 0;
1020 while (bytes_read <
static_cast<size_t>(size)) {
1021 size_t to_read = std::min(chunk_size,
1022 static_cast<size_t>(size) - bytes_read);
1023 file.read(
reinterpret_cast<char*
>(buffer.data() + bytes_read),
1024 static_cast<std::streamsize
>(to_read));
1026 return std::vector<uint8_t>{};
1028 bytes_read += to_read;
1030 callback(bytes_read,
static_cast<size_t>(size));
1043 std::string path_str(path);
1044 std::vector<uint8_t> data_copy(data.begin(), data.end());
1046 [path_str, data_copy = std::move(data_copy), callback]() {
1047 std::ofstream file(path_str, std::ios::binary);
1052 const size_t chunk_size = 64 * 1024;
1053 size_t bytes_written = 0;
1054 const size_t total_size = data_copy.size();
1056 while (bytes_written < total_size) {
1057 size_t to_write = std::min(chunk_size, total_size - bytes_written);
1058 file.write(
reinterpret_cast<const char*
>(data_copy.data() + bytes_written),
1059 static_cast<std::streamsize
>(to_write));
1063 bytes_written += to_write;
1065 callback(bytes_written, total_size);
1078 inline generator<std::vector<uint8_t>>
1081 auto serialize_result =
container_->serialize(serialization_format::binary);
1082 if (!serialize_result.is_ok()) {
1085 auto full_data = serialize_result.value();
1086 if (full_data.empty()) {
1090 const size_t total_size = full_data.size();
1093 while (offset < total_size) {
1094 size_t current_chunk_size = std::min(chunk_size, total_size - offset);
1095 std::vector<uint8_t> chunk(
1096 full_data.begin() +
static_cast<std::ptrdiff_t
>(offset),
1097 full_data.begin() +
static_cast<std::ptrdiff_t
>(offset + current_chunk_size));
1098 offset += current_chunk_size;
1105 std::span<const uint8_t> data,
1115 std::vector<uint8_t> data_copy(data.begin(), data.end());
1117 [data_copy = std::move(data_copy)]() {
1118 auto container = std::make_shared<value_container>(data_copy,
false);
Async wrapper for value_container operations.
static task< std::shared_ptr< value_container > > deserialize_streaming(std::span< const uint8_t > data, bool is_final=true)
Deserialize container progressively from chunks.
std::shared_ptr< value_container > get_container() const noexcept
Get the underlying container.
async_container(async_container &&other) noexcept=default
Move constructor.
std::optional< T > get(std::string_view key) const
Get a value from the container.
async_container & operator=(const async_container &)=delete
bool contains(std::string_view key) const noexcept
Check if container contains a key.
async_container()
Construct async_container with new empty container.
~async_container()=default
Destructor.
static task< std::shared_ptr< value_container > > deserialize_async(std::span< const uint8_t > data)
Deserialize from byte array asynchronously.
async_container(std::shared_ptr< value_container > container)
Construct async_container with existing container.
void set_container(std::shared_ptr< value_container > container) noexcept
Set the underlying container.
task< bool > load_async(std::string_view path, progress_callback callback=nullptr)
Load container from file asynchronously.
task< std::vector< uint8_t > > serialize_async() const
Serialize container to byte array asynchronously.
static task< std::shared_ptr< value_container > > deserialize_string_async(std::string_view data)
Deserialize from string asynchronously.
async_container & set(std::string_view key, T &&value)
Set a value in the container.
async_container & operator=(async_container &&other) noexcept=default
Move assignment operator.
std::shared_ptr< value_container > container_
task< std::string > serialize_string_async() const
Serialize container to string asynchronously.
generator< std::vector< uint8_t > > serialize_chunked(size_t chunk_size=64 *1024) const
Serialize container in chunks using generator.
async_container(const async_container &)=delete
task< bool > save_async(std::string_view path, progress_callback callback=nullptr)
Save container to file asynchronously.
Forward declaration of generator.
Forward declaration of task.
Enhanced type-safe value with perfect legacy compatibility.
C++20 coroutine generator for lazy sequence generation.
auto make_async_awaitable(F &&func) -> async_awaitable< std::invoke_result_t< F > >
std::function< void(size_t bytes_processed, size_t total_bytes)> progress_callback
Progress callback type for async file operations.
task< std::vector< uint8_t > > read_file_async(std::string_view path, progress_callback callback=nullptr)
Read file contents asynchronously.
task< bool > write_file_async(std::string_view path, std::span< const uint8_t > data, progress_callback callback=nullptr)
Write data to file asynchronously.
Awaitable that runs work in a separate thread.
async_awaitable(std::function< T()> work)
async_awaitable(async_awaitable &&) noexcept=default
std::shared_ptr< async_state< T > > state_
void await_suspend(std::coroutine_handle<> handle)
bool await_ready() const noexcept
Shared state for async operations.
std::optional< T > result_
std::exception_ptr exception_
async_state(const async_state &)=delete
async_state & operator=(const async_state &)=delete
std::atomic< bool > ready_
std::function< T()> work_
async_state(async_state &&)=delete
async_state & operator=(async_state &&)=delete
async_state(std::function< T()> work)
C++20 coroutine task type for async operations.