#pragma once namespace saw { namespace impl { template struct netcdf_is_group { static constexpr bool value = false; }; template struct netcdf_is_group...>> { static constexpr bool value = true; }; template struct netcdf_decode; template struct netcdf_decode { using Schema = schema::Int32; static error_or decode(data& to, int from, int nc_varid){ int rc{}; nc_type nc_vartype{}; int nc_dimnum{}; std::array nc_dimids; rc = nc_inq_var(from, nc_varid, nullptr, &nc_vartype, &nc_dimnum, &nc_dimids[0], nullptr); if(rc != NC_NOERR){ return make_error(); } if(nc_vartype != NC_INT){ return make_error(); } if(nc_dimnum != 0){ return make_error(); } int32_t val{}; rc = nc_get_var_int(from, nc_varid, &val); if(rc != NC_NOERR){ return make_error(); } to.set(val); return void_t {}; } }; template struct netcdf_decode...>, RootSchema, ToDecode> { using Schema = schema::Struct...>; template static error_or decode_member(data& to, int from){ using Type = typename parameter_pack_type::type; constexpr string_literal Literal = parameter_key_pack_type::literal; { /** * We have to ask for the internal id of the netcdf structure */ if constexpr (netcdf_is_group::value){ int nc_group_id{}; int rc {}; rc = nc_inq_ncid(from, Literal.data.data(), &nc_group_id); if(rc != NC_NOERR) { return make_error(); } auto eov = netcdf_decode::decode(to.template get(), nc_group_id); if(eov.is_error()){ return eov; } }else{ int nc_varid{}; int rc {}; rc = nc_inq_varid(from, Literal.data.data(), &nc_varid); if(rc != NC_NOERR) { return make_error(); } auto eov = netcdf_decode::decode(to.template get(), from, nc_varid); } } if constexpr ((i+1) < sizeof...(T)){ auto eov = decode_member(from, to, ncid); if(eov.is_error()){ return eov; } } return void_t{}; } static error_or decode(data& to, int from){ if constexpr (sizeof...(T) > 0){ auto eov = decode_member<0>(to, from); return eov; } return void_t{}; } }; } }