promises for async vfs operations

This commit is contained in:
2018-12-13 02:12:18 +07:00
parent ac885a51ef
commit af95e86764
9 changed files with 193 additions and 154 deletions

View File

@@ -178,16 +178,16 @@ namespace promise_hpp
then([ then([
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](const T& v) mutable { ](auto&& v) mutable {
auto np = invoke_hpp::invoke( auto np = invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
np.then([n]() mutable { std::move(np).then([n]() mutable {
n.resolve(); n.resolve();
}, [n](std::exception_ptr e) mutable { }).except([n](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
}, [n = next](std::exception_ptr e) mutable { }).except([n = next](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
@@ -205,16 +205,16 @@ namespace promise_hpp
then([ then([
n = next, n = next,
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](const T& v) mutable { ](auto&& v) mutable {
auto np = invoke_hpp::invoke( auto np = invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
np.then([n](const typename ResolveFR::value_type& nv) mutable { std::move(np).then([n](auto&& nv) mutable {
n.resolve(nv); n.resolve(std::forward<decltype(nv)>(nv));
}, [n](std::exception_ptr e) mutable { }).except([n](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
}, [n = next](std::exception_ptr e) mutable { }).except([n = next](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
@@ -225,10 +225,10 @@ namespace promise_hpp
auto then_all(ResolveF&& on_resolve) { auto then_all(ResolveF&& on_resolve) {
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](const T& v) mutable { ](auto&& v) mutable {
auto r = invoke_hpp::invoke( auto r = invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
return make_all_promise(std::move(r)); return make_all_promise(std::move(r));
}); });
} }
@@ -237,10 +237,10 @@ namespace promise_hpp
auto then_any(ResolveF&& on_resolve) { auto then_any(ResolveF&& on_resolve) {
return then([ return then([
f = std::forward<ResolveF>(on_resolve) f = std::forward<ResolveF>(on_resolve)
](const T& v) mutable { ](auto&& v) mutable {
auto r = invoke_hpp::invoke( auto r = invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
return make_any_promise(std::move(r)); return make_any_promise(std::move(r));
}); });
} }
@@ -274,14 +274,13 @@ namespace promise_hpp
template < typename RejectF > template < typename RejectF >
promise<T> except(RejectF&& on_reject) { promise<T> except(RejectF&& on_reject) {
return then( return then(
[](const T& value) { return value; }, [](auto&& v) { return std::forward<decltype(v)>(v); },
std::forward<RejectF>(on_reject)); std::forward<RejectF>(on_reject));
} }
template < typename U > template < typename U >
bool resolve(U&& value) { bool resolve(U&& value) {
return state_->resolve( return state_->resolve(std::forward<U>(value));
std::forward<U>(value));
} }
bool reject(std::exception_ptr e) noexcept { bool reject(std::exception_ptr e) noexcept {
@@ -298,6 +297,14 @@ namespace promise_hpp
return state_->get(); return state_->get();
} }
const T& get_or_default(const T& def) const noexcept {
try {
return get();
} catch (...) {
return def;
}
}
void wait() const noexcept { void wait() const noexcept {
state_->wait(); state_->wait();
} }
@@ -391,10 +398,10 @@ namespace promise_hpp
template < typename U, typename ResolveF, typename RejectF > template < typename U, typename ResolveF, typename RejectF >
std::enable_if_t<std::is_void<U>::value, void> std::enable_if_t<std::is_void<U>::value, void>
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) { attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
auto reject_h = [ auto reject_h = [
n = next, n = next,
f = std::forward<RejectF>(reject) f = std::forward<RejectF>(on_reject)
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
@@ -408,18 +415,15 @@ namespace promise_hpp
auto resolve_h = [ auto resolve_h = [
n = next, n = next,
f = std::forward<ResolveF>(resolve), f = std::forward<ResolveF>(on_resolve)
j = reject_h ](auto&& v) mutable {
](const T& v) mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
n.resolve(); n.resolve();
} catch (...) { } catch (...) {
invoke_hpp::invoke( n.reject(std::current_exception());
std::move(j),
std::current_exception());
} }
}; };
@@ -429,10 +433,10 @@ namespace promise_hpp
template < typename U, typename ResolveF, typename RejectF > template < typename U, typename ResolveF, typename RejectF >
std::enable_if_t<!std::is_void<U>::value, void> std::enable_if_t<!std::is_void<U>::value, void>
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) { attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
auto reject_h = [ auto reject_h = [
n = next, n = next,
f = std::forward<RejectF>(reject) f = std::forward<RejectF>(on_reject)
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
@@ -446,18 +450,15 @@ namespace promise_hpp
auto resolve_h = [ auto resolve_h = [
n = next, n = next,
f = std::forward<ResolveF>(resolve), f = std::forward<ResolveF>(on_resolve)
j = reject_h ](auto&& v) mutable {
](const T& v) mutable {
try { try {
auto r = invoke_hpp::invoke( auto r = invoke_hpp::invoke(
std::forward<decltype(f)>(f), std::forward<decltype(f)>(f),
v); std::forward<decltype(v)>(v));
n.resolve(std::move(r)); n.resolve(std::move(r));
} catch (...) { } catch (...) {
invoke_hpp::invoke( n.reject(std::current_exception());
std::move(j),
std::current_exception());
} }
}; };
@@ -576,12 +577,12 @@ namespace promise_hpp
]() mutable { ]() mutable {
auto np = invoke_hpp::invoke( auto np = invoke_hpp::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
np.then([n]() mutable { std::move(np).then([n]() mutable {
n.resolve(); n.resolve();
}, [n](std::exception_ptr e) mutable { }).except([n](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
}, [n = next](std::exception_ptr e) mutable { }).except([n = next](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
@@ -602,12 +603,12 @@ namespace promise_hpp
]() mutable { ]() mutable {
auto np = invoke_hpp::invoke( auto np = invoke_hpp::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
np.then([n](const typename ResolveFR::value_type& nv) mutable { std::move(np).then([n](auto&& nv) mutable {
n.resolve(nv); n.resolve(std::forward<decltype(nv)>(nv));
}, [n](std::exception_ptr e) mutable { }).except([n](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
}, [n = next](std::exception_ptr e) mutable { }).except([n = next](std::exception_ptr e) mutable {
n.reject(e); n.reject(e);
}); });
@@ -687,6 +688,14 @@ namespace promise_hpp
state_->get(); state_->get();
} }
void get_or_default() const noexcept {
try {
return get();
} catch (...) {
// nothing
}
}
void wait() const noexcept { void wait() const noexcept {
state_->wait(); state_->wait();
} }
@@ -777,10 +786,10 @@ namespace promise_hpp
template < typename U, typename ResolveF, typename RejectF > template < typename U, typename ResolveF, typename RejectF >
std::enable_if_t<std::is_void<U>::value, void> std::enable_if_t<std::is_void<U>::value, void>
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) { attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
auto reject_h = [ auto reject_h = [
n = next, n = next,
f = std::forward<RejectF>(reject) f = std::forward<RejectF>(on_reject)
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
@@ -794,17 +803,14 @@ namespace promise_hpp
auto resolve_h = [ auto resolve_h = [
n = next, n = next,
f = std::forward<ResolveF>(resolve), f = std::forward<ResolveF>(on_resolve)
j = reject_h
]() mutable { ]() mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
n.resolve(); n.resolve();
} catch (...) { } catch (...) {
invoke_hpp::invoke( n.reject(std::current_exception());
std::move(j),
std::current_exception());
} }
}; };
@@ -814,10 +820,10 @@ namespace promise_hpp
template < typename U, typename ResolveF, typename RejectF > template < typename U, typename ResolveF, typename RejectF >
std::enable_if_t<!std::is_void<U>::value, void> std::enable_if_t<!std::is_void<U>::value, void>
attach(promise<U>& next, ResolveF&& resolve, RejectF&& reject) { attach(promise<U>& next, ResolveF&& on_resolve, RejectF&& on_reject) {
auto reject_h = [ auto reject_h = [
n = next, n = next,
f = std::forward<RejectF>(reject) f = std::forward<RejectF>(on_reject)
](std::exception_ptr e) mutable { ](std::exception_ptr e) mutable {
try { try {
invoke_hpp::invoke( invoke_hpp::invoke(
@@ -831,17 +837,14 @@ namespace promise_hpp
auto resolve_h = [ auto resolve_h = [
n = next, n = next,
f = std::forward<ResolveF>(resolve), f = std::forward<ResolveF>(on_resolve)
j = reject_h
]() mutable { ]() mutable {
try { try {
auto r = invoke_hpp::invoke( auto r = invoke_hpp::invoke(
std::forward<decltype(f)>(f)); std::forward<decltype(f)>(f));
n.resolve(std::move(r)); n.resolve(std::move(r));
} catch (...) { } catch (...) {
invoke_hpp::invoke( n.reject(std::current_exception());
std::move(j),
std::current_exception());
} }
}; };
@@ -1020,11 +1023,11 @@ namespace promise_hpp
context, context,
resolver, resolver,
result_index result_index
](const child_promise_value_t& v) mutable { ](auto&& v) mutable {
if ( context->apply_result(result_index, v) ) { if ( context->apply_result(result_index, std::forward<decltype(v)>(v)) ) {
resolver(std::move(context->results)); resolver(std::move(context->results));
} }
}, rejector); }).except(rejector);
} }
}); });
} }
@@ -1051,7 +1054,7 @@ namespace promise_hpp
return make_promise<child_promise_value_t>([begin, end](auto&& resolver, auto&& rejector){ return make_promise<child_promise_value_t>([begin, end](auto&& resolver, auto&& rejector){
for ( auto iter = begin; iter != end; ++iter ) { for ( auto iter = begin; iter != end; ++iter ) {
(*iter).then(resolver, rejector); (*iter).then(resolver).except(rejector);
} }
}); });
} }

View File

@@ -17,6 +17,12 @@ namespace e2d
} }
}; };
class vfs_load_async_exception final : public exception {
const char* what() const noexcept final {
return "vfs load async exception";
}
};
class vfs final : public module<vfs> { class vfs final : public module<vfs> {
public: public:
vfs(); vfs();
@@ -27,8 +33,7 @@ namespace e2d
virtual ~file_source() noexcept = default; virtual ~file_source() noexcept = default;
virtual bool valid() const noexcept = 0; virtual bool valid() const noexcept = 0;
virtual bool exists(str_view path) const = 0; virtual bool exists(str_view path) const = 0;
virtual input_stream_uptr open(str_view path) const = 0; virtual input_stream_uptr read(str_view path) const = 0;
virtual std::pair<buffer,bool> load(str_view path) const = 0;
virtual output_stream_uptr write(str_view path, bool append) const = 0; virtual output_stream_uptr write(str_view path, bool append) const = 0;
virtual bool trace(str_view path, filesystem::trace_func func) const = 0; virtual bool trace(str_view path, filesystem::trace_func func) const = 0;
}; };
@@ -43,10 +48,15 @@ namespace e2d
bool unregister_scheme_alias(str_view scheme); bool unregister_scheme_alias(str_view scheme);
bool exists(const url& url) const; bool exists(const url& url) const;
input_stream_uptr open(const url& url) const;
std::pair<buffer,bool> load(const url& url) const; input_stream_uptr read(const url& url) const;
output_stream_uptr write(const url& url, bool append) const; output_stream_uptr write(const url& url, bool append) const;
stdex::promise<std::pair<buffer,bool>> load_async(const url& url) const;
bool load(const url& url, buffer& dst) const;
stdex::promise<buffer> load_async(const url& url) const;
bool load_as_string(const url& url, str& dst) const;
stdex::promise<str> load_as_string_async(const url& url) const;
template < typename Iter > template < typename Iter >
bool extract(const url& url, Iter result_iter) const; bool extract(const url& url, Iter result_iter) const;
@@ -64,8 +74,7 @@ namespace e2d
~archive_file_source() noexcept final; ~archive_file_source() noexcept final;
bool valid() const noexcept final; bool valid() const noexcept final;
bool exists(str_view path) const final; bool exists(str_view path) const final;
input_stream_uptr open(str_view path) const final; input_stream_uptr read(str_view path) const final;
std::pair<buffer,bool> load(str_view path) const final;
output_stream_uptr write(str_view path, bool append) const final; output_stream_uptr write(str_view path, bool append) const final;
bool trace(str_view path, filesystem::trace_func func) const final; bool trace(str_view path, filesystem::trace_func func) const final;
private: private:
@@ -79,8 +88,7 @@ namespace e2d
~filesystem_file_source() noexcept final; ~filesystem_file_source() noexcept final;
bool valid() const noexcept final; bool valid() const noexcept final;
bool exists(str_view path) const final; bool exists(str_view path) const final;
input_stream_uptr open(str_view path) const final; input_stream_uptr read(str_view path) const final;
std::pair<buffer,bool> load(str_view path) const final;
output_stream_uptr write(str_view path, bool append) const final; output_stream_uptr write(str_view path, bool append) const final;
bool trace(str_view path, filesystem::trace_func func) const final; bool trace(str_view path, filesystem::trace_func func) const final;
}; };

View File

@@ -95,7 +95,7 @@ namespace
bool initialize() final { bool initialize() final {
the<vfs>().register_scheme<archive_file_source>( the<vfs>().register_scheme<archive_file_source>(
"piratepack", "piratepack",
the<vfs>().open(url("resources://bin/kenney_piratepack.zip"))); the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
the<vfs>().register_scheme_alias( the<vfs>().register_scheme_alias(
"ships", "ships",
@@ -104,9 +104,9 @@ namespace
shader_ = the<render>().create_shader( shader_ = the<render>().create_shader(
vs_source_cstr, fs_source_cstr); vs_source_cstr, fs_source_cstr);
texture1_ = the<render>().create_texture( texture1_ = the<render>().create_texture(
the<vfs>().open(url("ships://ship (2).png"))); the<vfs>().read(url("ships://ship (2).png")));
texture2_ = the<render>().create_texture( texture2_ = the<render>().create_texture(
the<vfs>().open(url("ships://ship (19).png"))); the<vfs>().read(url("ships://ship (19).png")));
if ( !shader_ || !texture1_ || !texture2_ ) { if ( !shader_ || !texture1_ || !texture2_ ) {
return false; return false;

View File

@@ -155,7 +155,7 @@ namespace
bool initialize() final { bool initialize() final {
the<vfs>().register_scheme<archive_file_source>( the<vfs>().register_scheme<archive_file_source>(
"piratepack", "piratepack",
the<vfs>().open(url("resources://bin/kenney_piratepack.zip"))); the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
the<vfs>().register_scheme_alias( the<vfs>().register_scheme_alias(
"ships", "ships",
@@ -165,7 +165,7 @@ namespace
vs_source_cstr, fs_source_cstr); vs_source_cstr, fs_source_cstr);
texture_ = the<render>().create_texture( texture_ = the<render>().create_texture(
the<vfs>().open(url("ships://ship (3).png"))); the<vfs>().read(url("ships://ship (3).png")));
if ( !shader_ || !texture_ ) { if ( !shader_ || !texture_ ) {
return false; return false;

View File

@@ -110,7 +110,7 @@ namespace
bool initialize() final { bool initialize() final {
the<vfs>().register_scheme<archive_file_source>( the<vfs>().register_scheme<archive_file_source>(
"piratepack", "piratepack",
the<vfs>().open(url("resources://bin/kenney_piratepack.zip"))); the<vfs>().read(url("resources://bin/kenney_piratepack.zip")));
the<vfs>().register_scheme_alias( the<vfs>().register_scheme_alias(
"ships", "ships",
@@ -120,7 +120,7 @@ namespace
vs_source_cstr, fs_source_cstr); vs_source_cstr, fs_source_cstr);
texture_ = the<render>().create_texture( texture_ = the<render>().create_texture(
the<vfs>().open(url("ships://ship (3).png"))); the<vfs>().read(url("ships://ship (3).png")));
if ( !shader_ || !texture_ ) { if ( !shader_ || !texture_ ) {
return false; return false;

View File

@@ -98,7 +98,10 @@ namespace e2d
const auto resolved_url = resolve_url(url); const auto resolved_url = resolve_url(url);
const auto scheme_iter = schemes.find(resolved_url.scheme()); const auto scheme_iter = schemes.find(resolved_url.scheme());
return (scheme_iter != schemes.cend() && scheme_iter->second) return (scheme_iter != schemes.cend() && scheme_iter->second)
? stdex::invoke(std::forward<F>(f), scheme_iter->second, resolved_url.path()) ? stdex::invoke(
std::forward<F>(f),
scheme_iter->second,
resolved_url.path())
: std::forward<R>(fallback_result); : std::forward<R>(fallback_result);
} }
}; };
@@ -140,22 +143,14 @@ namespace e2d
}, false); }, false);
} }
input_stream_uptr vfs::open(const url& url) const { input_stream_uptr vfs::read(const url& url) const {
std::lock_guard<std::mutex> guard(state_->mutex); std::lock_guard<std::mutex> guard(state_->mutex);
return state_->with_file_source(url, return state_->with_file_source(url,
[](const file_source_uptr& source, const str& path) { [](const file_source_uptr& source, const str& path) {
return source->open(path); return source->read(path);
}, input_stream_uptr()); }, input_stream_uptr());
} }
std::pair<buffer,bool> vfs::load(const url& url) const {
std::lock_guard<std::mutex> guard(state_->mutex);
return state_->with_file_source(url,
[](const file_source_uptr& source, const str& path) {
return source->load(path);
}, std::make_pair(buffer(), false));
}
output_stream_uptr vfs::write(const url& url, bool append) const { output_stream_uptr vfs::write(const url& url, bool append) const {
std::lock_guard<std::mutex> guard(state_->mutex); std::lock_guard<std::mutex> guard(state_->mutex);
return state_->with_file_source(url, return state_->with_file_source(url,
@@ -164,13 +159,40 @@ namespace e2d
}, output_stream_uptr()); }, output_stream_uptr());
} }
stdex::promise<std::pair<buffer,bool>> vfs::load_async(const url& url) const { bool vfs::load(const url& url, buffer& dst) const {
return state_->worker.async([](input_stream_uptr stream){ return load_async(url)
buffer buf; .then([&dst](auto&& src){
return streams::try_read_tail(buf, stream) dst = std::forward<decltype(src)>(src);
? std::make_pair(std::move(buf), true) return true;
: std::make_pair(buffer(), false); }).get_or_default(false);
}, open(url)); }
stdex::promise<buffer> vfs::load_async(const url& url) const {
return state_->worker.async([this](auto&& url_copy){
buffer content;
if ( !streams::try_read_tail(content, read(url_copy)) ) {
throw vfs_load_async_exception();
}
return content;
}, url);
}
bool vfs::load_as_string(const url& url, str& dst) const {
return load_as_string_async(url)
.then([&dst](auto&& src){
dst = std::forward<decltype(src)>(src);
return true;
}).get_or_default(false);
}
stdex::promise<str> vfs::load_as_string_async(const url& url) const {
return state_->worker.async([this](auto&& url_copy){
str content;
if ( !streams::try_read_tail(content, read(url_copy)) ) {
throw vfs_load_async_exception();
}
return content;
}, url);
} }
bool vfs::trace(const url& url, filesystem::trace_func func) const { bool vfs::trace(const url& url, filesystem::trace_func func) const {
@@ -250,7 +272,7 @@ namespace e2d
MZ_ZIP_FLAG_CASE_SENSITIVE); MZ_ZIP_FLAG_CASE_SENSITIVE);
} }
input_stream_uptr archive_file_source::open(str_view path) const { input_stream_uptr archive_file_source::read(str_view path) const {
try { try {
struct owned_state_t { struct owned_state_t {
state::archive_ptr archive; state::archive_ptr archive;
@@ -265,19 +287,6 @@ namespace e2d
} }
} }
std::pair<buffer,bool> archive_file_source::load(str_view path) const {
std::size_t mem_size = 0;
void* mem = mz_zip_reader_extract_file_to_heap(
state_->archive.get(),
make_utf8(path).c_str(),
&mem_size,
MZ_ZIP_FLAG_CASE_SENSITIVE);
std::unique_ptr<void, decltype(&mz_free)> mem_uptr(mem, mz_free);
return mem
? std::make_pair(buffer(mem, mem_size), true)
: std::make_pair(buffer(), false);
}
output_stream_uptr archive_file_source::write(str_view path, bool append) const { output_stream_uptr archive_file_source::write(str_view path, bool append) const {
E2D_UNUSED(path, append); E2D_UNUSED(path, append);
return nullptr; return nullptr;
@@ -338,17 +347,10 @@ namespace e2d
return filesystem::file_exists(path); return filesystem::file_exists(path);
} }
input_stream_uptr filesystem_file_source::open(str_view path) const { input_stream_uptr filesystem_file_source::read(str_view path) const {
return make_read_file(path); return make_read_file(path);
} }
std::pair<buffer,bool> filesystem_file_source::load(str_view path) const {
buffer buf;
return filesystem::try_read_all(buf, path)
? std::make_pair(std::move(buf), true)
: std::make_pair(buffer(), false);
}
output_stream_uptr filesystem_file_source::write(str_view path, bool append) const { output_stream_uptr filesystem_file_source::write(str_view path, bool append) const {
if ( !filesystem::create_directory_recursive(path::parent_path(path)) ) { if ( !filesystem::create_directory_recursive(path::parent_path(path)) ) {
return nullptr; return nullptr;

View File

@@ -1390,7 +1390,7 @@ namespace e2d
const auto asset_url = library.root() / address; const auto asset_url = library.root() / address;
input_stream_uptr stream = modules::is_initialized<vfs>() input_stream_uptr stream = modules::is_initialized<vfs>()
? the<vfs>().open(asset_url) ? the<vfs>().read(asset_url)
: input_stream_uptr(); : input_stream_uptr();
if ( !stream ) { if ( !stream ) {
@@ -1462,7 +1462,7 @@ namespace e2d
const auto asset_url = library.root() / address; const auto asset_url = library.root() / address;
input_stream_uptr stream = modules::is_initialized<vfs>() input_stream_uptr stream = modules::is_initialized<vfs>()
? the<vfs>().open(asset_url) ? the<vfs>().read(asset_url)
: input_stream_uptr(); : input_stream_uptr();
if ( !stream ) { if ( !stream ) {

View File

@@ -25,21 +25,27 @@ TEST_CASE("vfs"){
} }
{ {
buffer b; buffer b;
auto r = v.open({"file", file_path}); auto r = v.read({"file", file_path});
REQUIRE(r); REQUIRE(r);
REQUIRE(streams::try_read_tail(b, r)); REQUIRE(streams::try_read_tail(b, r));
REQUIRE(b == buffer{"hello", 5}); REQUIRE(b == buffer{"hello", 5});
REQUIRE(v.open({"file2", file_path}) == input_stream_uptr()); REQUIRE(v.read({"file2", file_path}) == input_stream_uptr());
REQUIRE(v.open({"file", nofile_path}) == input_stream_uptr()); REQUIRE(v.read({"file", nofile_path}) == input_stream_uptr());
} }
{ {
auto r = v.load({"file", file_path}); buffer b0;
REQUIRE(r.second); REQUIRE(v.load({"file", file_path}, b0));
REQUIRE(r.first == buffer{"hello", 5}); REQUIRE(b0 == buffer{"hello", 5});
auto r2 = v.load_async({"file", file_path}).get(); auto b1 = v.load_async({"file", file_path}).get();
REQUIRE(r2.second); REQUIRE(b1 == buffer{"hello", 5});
REQUIRE(r2.first == buffer{"hello", 5});
str b2;
REQUIRE(v.load_as_string({"file", file_path}, b2));
REQUIRE(b2 == "hello");
auto b3 = v.load_as_string_async({"file", file_path}).get();
REQUIRE(b3 == "hello");
} }
} }
{ {
@@ -58,17 +64,17 @@ TEST_CASE("vfs"){
REQUIRE_FALSE(v.register_scheme<archive_file_source>( REQUIRE_FALSE(v.register_scheme<archive_file_source>(
"archive", "archive",
v.open(url("resources://bin/noresources.zip")))); v.read(url("resources://bin/noresources.zip"))));
REQUIRE(v.register_scheme<filesystem_file_source>("file")); REQUIRE(v.register_scheme<filesystem_file_source>("file"));
REQUIRE_FALSE(v.register_scheme<archive_file_source>( REQUIRE_FALSE(v.register_scheme<archive_file_source>(
"archive", "archive",
v.open(url("resources://bin/noresources.zip")))); v.read(url("resources://bin/noresources.zip"))));
REQUIRE(v.register_scheme<archive_file_source>( REQUIRE(v.register_scheme<archive_file_source>(
"archive", "archive",
v.open(url("resources://bin/resources.zip")))); v.read(url("resources://bin/resources.zip"))));
REQUIRE(v.exists({"archive", "test.txt"})); REQUIRE(v.exists({"archive", "test.txt"}));
REQUIRE_FALSE(v.exists({"archive", "TEst.txt"})); REQUIRE_FALSE(v.exists({"archive", "TEst.txt"}));
@@ -122,50 +128,70 @@ TEST_CASE("vfs"){
REQUIRE_FALSE(v.extract(url("archive://test.txt"), std::back_inserter(result))); REQUIRE_FALSE(v.extract(url("archive://test.txt"), std::back_inserter(result)));
} }
{ {
auto f = v.open(url("archive://test.txt")); auto f = v.read(url("archive://test.txt"));
REQUIRE(f); REQUIRE(f);
buffer b; buffer b;
REQUIRE(streams::try_read_tail(b, f)); REQUIRE(streams::try_read_tail(b, f));
REQUIRE(b == buffer("hello", 5)); REQUIRE(b == buffer("hello", 5));
} }
{ {
auto r = v.load(url("archive://test.txt")); buffer b0;
REQUIRE(r.second); REQUIRE(v.load(url("archive://test.txt"), b0));
REQUIRE(r.first == buffer("hello", 5)); REQUIRE(b0 == buffer("hello", 5));
auto r2 = v.load_async(url("archive://test.txt")).get(); auto b1 = v.load_async(url("archive://test.txt")).get();
REQUIRE(r2.second); REQUIRE(b1 == buffer("hello", 5));
REQUIRE(r2.first == buffer("hello", 5));
str b2;
REQUIRE(v.load_as_string(url("archive://test.txt"), b2));
REQUIRE(b2 == "hello");
auto b3 = v.load_as_string_async(url("archive://test.txt")).get();
REQUIRE(b3 == "hello");
} }
{ {
auto f = v.open(url("archive://folder/file.txt")); auto f = v.read(url("archive://folder/file.txt"));
REQUIRE(f); REQUIRE(f);
buffer b; buffer b;
REQUIRE(streams::try_read_tail(b, f)); REQUIRE(streams::try_read_tail(b, f));
REQUIRE(b == buffer("world", 5)); REQUIRE(b == buffer("world", 5));
} }
{ {
auto r = v.load(url("archive://folder/file.txt")); buffer b0;
REQUIRE(r.second); REQUIRE(v.load(url("archive://folder/file.txt"), b0));
REQUIRE(r.first == buffer("world", 5)); REQUIRE(b0 == buffer("world", 5));
auto r2 = v.load_async(url("archive://folder/file.txt")).get(); auto b1 = v.load_async(url("archive://folder/file.txt")).get();
REQUIRE(r2.second); REQUIRE(b1 == buffer("world", 5));
REQUIRE(r2.first == buffer("world", 5));
str b2;
REQUIRE(v.load_as_string(url("archive://folder/file.txt"), b2));
REQUIRE(b2 == "world");
auto b3 = v.load_as_string_async(url("archive://folder/file.txt")).get();
REQUIRE(b3 == "world");
} }
{ {
REQUIRE(v.open(url("archive://TEst.txt")) == input_stream_uptr()); REQUIRE(v.read(url("archive://TEst.txt")) == input_stream_uptr());
auto r = v.load(url("archive://TEst.txt")); buffer b0;
REQUIRE_FALSE(r.second); REQUIRE_FALSE(v.load(url("archive://TEst.txt"), b0));
REQUIRE(r.first.empty()); REQUIRE(b0.empty());
auto r2 = v.load_async(url("archive://TEst.txt")).get(); REQUIRE_THROWS_AS(
REQUIRE_FALSE(r2.second); v.load_async(url("archive://TEst.txt")).get(),
REQUIRE(r2.first.empty()); vfs_load_async_exception);
str b2;
REQUIRE_FALSE(v.load_as_string(url("archive://TEst.txt"), b2));
REQUIRE(b2.empty());
REQUIRE_THROWS_AS(
v.load_as_string_async(url("archive://TEst.txt")).get(),
vfs_load_async_exception);
} }
{ {
auto f = v.open(url("archive://test.txt")); auto f = v.read(url("archive://test.txt"));
REQUIRE(f); REQUIRE(f);
REQUIRE(v.unregister_scheme("archive")); REQUIRE(v.unregister_scheme("archive"));
buffer b; buffer b;