io::reader prepared_item::make_reader()

in src/native/diffs/core/prepared_item.cpp [45:109]


io::reader prepared_item::make_reader()
{
	return std::visit(
		overload{
			[](reader_kind &kind) { return kind.m_factory->make_reader(); },
			[](sequential_reader_kind &kind)
			{
				auto temp_file = std::make_shared<io::file::temp_file>();

				auto seq_reader = kind.m_factory->make_sequential_reader();

				io::shared_writer writer = std::make_shared<io::file::temp_file_writer>(temp_file);
				io::sequential::basic_writer_wrapper wrapper(writer);

				wrapper.write(*seq_reader);

				return io::file::temp_file_io_device::make_reader(temp_file);
			},
			[](slice_kind &kind)
			{
				auto reader = kind.m_item->make_reader();
				return reader.slice(kind.m_offset, kind.m_length);
			},
			[](chain_kind &kind)
			{
				std::vector<io::reader> readers;
				for (auto &item : kind.m_items)
				{
					readers.push_back(item->make_reader());
				}
				return io::reader::chain(readers);
			},
			[&](fetch_slice_kind &kind)
			{
				// printf("Fetching slice from kitchen...\n");
				std::shared_ptr<prepared_item> result;

				// We're going to try to mutate into the reader version
		        // by fetching from the kitchen.
		        // We may wait here while more works is done as a result.
				if (auto kitchen = kind.kitchen.lock())
				{
					result = kitchen->fetch_slice(m_item_definition);
				}
				else
				{
					// kitchen is gone!
					ADU_LOG("Kitchen missing when trying to prepare reader.");
					throw errors::user_exception(errors::error_code::diffs_prepared_item_kitchen_gone);
				}

				if (!std::holds_alternative<reader_kind>(result->m_kind))
				{
					throw errors::user_exception(
						errors::error_code::diffs_prepared_item_wrong_kind, "Fetched item not reader kind");
				}

				m_kind = result->m_kind;

				auto &factory = std::get<reader_kind>(m_kind).m_factory;
				return factory->make_reader();
			},
		},
		m_kind);
}