@@ -306,15 +306,123 @@ namespace
306306 " ' (accepted values are 'dataset' and 'template'." );
307307 }
308308 }
309+
310+ template <typename T, typename OrElse>
311+ auto optionalOrElse (std::optional<T> o, OrElse &&orElse) -> T
312+ {
313+ if (o.has_value ())
314+ {
315+ return *std::move (o);
316+ }
317+ else
318+ {
319+ return std::forward<OrElse>(orElse)();
320+ }
321+ }
322+
309323 void parse_external_mode (
310- [[maybe_unused]] json::TracingJSON mode,
311- [[maybe_unused]] std::string const &configLocation,
324+ json::TracingJSON mode,
325+ std::string const &configLocation,
312326 JSONIOHandlerImpl::DatasetMode_s &res)
313327 {
314328 using SpecificationVia = JSONIOHandlerImpl::SpecificationVia;
329+ using ExternalBlockStorage = openPMD::ExternalBlockStorage;
330+
331+ auto get_mandatory = [&](char const *key,
332+ bool lowercase) -> std::string {
333+ if (!mode.json ().contains (key))
334+ {
335+ throw error::BackendConfigSchema (
336+ {configLocation, " mode" , key}, " Mandatory key." );
337+ }
338+ auto const &val = mode.json ({key});
339+ return optionalOrElse (
340+ lowercase ? openPMD::json::asLowerCaseStringDynamic (val)
341+ : openPMD::json::asStringDynamic (val),
342+ [&]() -> std::string {
343+ throw error::BackendConfigSchema (
344+ {configLocation, " mode" , key},
345+ " Must be of string type." );
346+ });
347+ };
348+ auto if_contains_optional =
349+ [&](char const *key, bool lowercase, auto &&then) {
350+ if (!mode.json ().contains (key))
351+ {
352+ return ;
353+ }
354+ auto const &val = mode.json ({key});
355+ static_cast <decltype (then)>(then)(optionalOrElse (
356+ lowercase ? openPMD::json::asLowerCaseStringDynamic (val)
357+ : openPMD::json::asStringDynamic (val),
358+ [&]() -> std::string {
359+ throw error::BackendConfigSchema (
360+ {configLocation, " mode" , key},
361+ " Must be of string type." );
362+ }));
363+ };
364+ auto modeString = get_mandatory (" type" , true );
365+
366+ if (modeString == " stdio" )
367+ {
368+ auto builder = ExternalBlockStorage::makeStdioSession (
369+ get_mandatory (" directory" , false ));
370+
371+ if_contains_optional (" open_mode" , false , [&](std::string openMode) {
372+ builder.setOpenMode (std::move (openMode));
373+ });
374+
375+ res.m_mode =
376+ std::make_shared<ExternalBlockStorage>(builder.build ());
377+ }
378+ else if (modeString == " aws" )
379+ {
380+ openPMD::internal::AwsBuilder builder (
381+ get_mandatory (" bucket_name" , false ),
382+ get_mandatory (" access_key_id" , false ),
383+ get_mandatory (" secret_access_key" , false ));
384+
385+ if_contains_optional (
386+ " session_token" , false , [&](std::string sessionToken) {
387+ builder.setSessionToken (std::move (sessionToken));
388+ });
389+ if_contains_optional (
390+ " endpoint" , false , [&](std::string endpointOverride) {
391+ builder.setEndpointOverride (std::move (endpointOverride));
392+ });
393+ if_contains_optional (" region" , false , [&](std::string region) {
394+ builder.setRegion (std::move (region));
395+ });
396+ if_contains_optional (
397+ " scheme" , true , [&](std::string const &scheme) {
398+ if (scheme == " http" )
399+ {
400+ builder.setScheme (
401+ openPMD::internal::AwsBuilder::Scheme::HTTP);
402+ }
403+ else if (scheme == " https" )
404+ {
405+ builder.setScheme (
406+ openPMD::internal::AwsBuilder::Scheme::HTTPS);
407+ }
408+ else
409+ {
410+ throw error::BackendConfigSchema (
411+ {configLocation, " mode" , " scheme" },
412+ " Must be either 'http' or 'https'." );
413+ }
414+ });
415+
416+ res.m_mode =
417+ std::make_shared<ExternalBlockStorage>(builder.build ());
418+ }
419+ else
420+ {
421+ throw error::BackendConfigSchema (
422+ {configLocation, " mode" , " type" },
423+ " Must be either 'stdio' or 'aws'." );
424+ }
315425
316- res.m_mode = std::make_shared<ExternalBlockStorage>(
317- ExternalBlockStorage::makeStdioSession (" ./external_blocks" ));
318426 res.m_specificationVia = SpecificationVia::Manually;
319427 }
320428} // namespace
0 commit comments