diff options
author | Claudius "keldu" Holeksa <mail@keldu.de> | 2025-04-07 14:20:42 +0200 |
---|---|---|
committer | Claudius "keldu" Holeksa <mail@keldu.de> | 2025-04-07 14:20:42 +0200 |
commit | fe53a6cc42b645cab62515e257f52426ae568753 (patch) | |
tree | 3452e3a13d60cc2daac00d2472472bc83dfa451e | |
parent | b192777212c3de6a9d25c5519269d9047865b2d1 (diff) |
Copied netcdf for vtk preparation
-rw-r--r-- | modules/codec-vtk/.nix/derivation.nix | 37 | ||||
-rw-r--r-- | modules/codec-vtk/SConstruct | 73 | ||||
-rw-r--r-- | modules/codec-vtk/c++/SConscript | 38 | ||||
-rw-r--r-- | modules/codec-vtk/c++/netcdf.hpp | 148 | ||||
-rw-r--r-- | modules/codec-vtk/c++/netcdf.tmpl.hpp | 348 | ||||
-rw-r--r-- | modules/codec-vtk/tests/SConscript | 31 | ||||
-rw-r--r-- | modules/codec-vtk/tests/codec-netcdf.cpp | 104 |
7 files changed, 779 insertions, 0 deletions
diff --git a/modules/codec-vtk/.nix/derivation.nix b/modules/codec-vtk/.nix/derivation.nix new file mode 100644 index 0000000..00f610d --- /dev/null +++ b/modules/codec-vtk/.nix/derivation.nix @@ -0,0 +1,37 @@ +{ lib +, stdenv +, scons +, clang +, clang-tools +, version +, forstio +}: + +let + +in stdenv.mkDerivation { + pname = "forstio-codec-vtk"; + inherit version; + src = ./..; + + enableParallelBuilding = true; + + nativeBuildInputs = [ + scons + clang-tools + ]; + + buildInputs = [ + forstio.core + forstio.async + forstio.codec + ]; + + doCheck = true; + checkPhase = '' + scons test + ./bin/tests + ''; + + outputs = ["out" "dev"]; +} diff --git a/modules/codec-vtk/SConstruct b/modules/codec-vtk/SConstruct new file mode 100644 index 0000000..adabe4b --- /dev/null +++ b/modules/codec-vtk/SConstruct @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +import sys +import os +import os.path +import glob +import re + + +if sys.version_info < (3,): + def isbasestring(s): + return isinstance(s,basestring) +else: + def isbasestring(s): + return isinstance(s, (str,bytes)) + +def add_kel_source_files(self, sources, filetype, lib_env=None, shared=False, target_post=""): + + if isbasestring(filetype): + dir_path = self.Dir('.').abspath + filetype = sorted(glob.glob(dir_path+"/"+filetype)) + + for path in filetype: + target_name = re.sub( r'(.*?)(\.cpp|\.c\+\+)', r'\1' + target_post, path ) + if shared: + target_name+='.os' + sources.append( self.SharedObject( target=target_name, source=path ) ) + else: + target_name+='.o' + sources.append( self.StaticObject( target=target_name, source=path ) ) + pass + +def isAbsolutePath(key, dirname, env): + assert os.path.isabs(dirname), "%r must have absolute path syntax" % (key,) + +env_vars = Variables( + args=ARGUMENTS +) + +env_vars.Add('prefix', + help='Installation target location of build results and headers', + default='/usr/local/', + validator=isAbsolutePath +) + +env=Environment(ENV=os.environ, variables=env_vars, CPPPATH=[], + CXX=['c++'], + CPPDEFINES=['SAW_UNIX'], + CXXFLAGS=['-std=c++20','-g','-Wall','-Wextra'], + LIBS=[ + 'forstio-core', + 'forstio-codec', + 'netcdf' + ] +); +env.__class__.add_source_files = add_kel_source_files +env.Tool('compilation_db'); +env.cdb = env.CompilationDatabase('compile_commands.json'); + +env.objects = []; +env.sources = []; +env.headers = []; +env.targets = []; + +Export('env') +SConscript('c++/SConscript') +SConscript('tests/SConscript') + +env.Alias('cdb', env.cdb); +env.Alias('all', [env.targets]); +env.Default('all'); + +env.Alias('install', '$prefix') diff --git a/modules/codec-vtk/c++/SConscript b/modules/codec-vtk/c++/SConscript new file mode 100644 index 0000000..6d8866b --- /dev/null +++ b/modules/codec-vtk/c++/SConscript @@ -0,0 +1,38 @@ +#!/bin/false + +import os +import os.path +import glob + + +Import('env') + +dir_path = Dir('.').abspath + +# Environment for base library +codec_netcdf_env = env.Clone(); + +codec_netcdf_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) +codec_netcdf_env.headers = sorted(glob.glob(dir_path + "/*.hpp")) + +env.sources += codec_netcdf_env.sources; +env.headers += codec_netcdf_env.headers; + +## Shared lib +objects_shared = [] +codec_netcdf_env.add_source_files(objects_shared, codec_netcdf_env.sources, shared=True); +env.library_shared = codec_netcdf_env.SharedLibrary('#build/forstio-codec-netcdf', [objects_shared]); + +## Static lib +objects_static = [] +codec_netcdf_env.add_source_files(objects_static, codec_netcdf_env.sources, shared=False); +env.library_static = codec_netcdf_env.StaticLibrary('#build/forstio-codec-netcdf', [objects_static]); + +# Set Alias +env.Alias('library_codec_netcdf', [env.library_shared, env.library_static]); + +env.targets += ['library_codec_netcdf']; + +# Install +env.Install('$prefix/lib/', [env.library_shared, env.library_static]); +env.Install('$prefix/include/forstio/codec/netcdf/', [codec_netcdf_env.headers]); diff --git a/modules/codec-vtk/c++/netcdf.hpp b/modules/codec-vtk/c++/netcdf.hpp new file mode 100644 index 0000000..2c0a786 --- /dev/null +++ b/modules/codec-vtk/c++/netcdf.hpp @@ -0,0 +1,148 @@ +#pragma once + +#include <forstio/string_literal.hpp> +#include <forstio/error.hpp> +#include <forstio/codec/data.hpp> + +namespace saw { +namespace encode { +/** + * Template type hint + */ +struct VtkLegacy {}; +} + +/** + * Class representing the files system netcdf file + */ +template<typename Schema> +class data<Schema, encode::VtkLegacy> { +private: + std::vector<uint8_t> buff_; +public: + data() = default; + + data(std::vector<uint8_t> buff): + buff_{std::move(buff)} + {} + + template<size_t N> + data(const std::array<uint8_t, N>& arr): + buff_{arr.begin(), arr.end()} + {} + + std::vector<uint8_t>& get_data() { + return buff_; + } + + const std::vector<uint8_t>& get_data() const { + return buff_; + } +}; + +template<typename Schema> +class codec<Schema, encode::VtkLegacy>{ + static_assert(always_false<Schema,encode::VtkLegacy>, "NetCDF only supports Structs as a root object"); +}; + +} +#include "vtk.tmpl.hpp" +namespace saw { + +template<typename... Vals, string_literal... Keys> +class codec<schema::Struct<schema::Member<Vals,Keys>...>, encode::VtkLegacy> { +private: + using Schema = schema::Struct<schema::Member<Vals,Keys>...>; +public: + SAW_FORBID_COPY(codec); + SAW_DEFAULT_MOVE(codec); + + /** + * Default constructor + */ + codec() = default; + + /** + * Encoder function + */ + template<typename FromEncoding> + error_or<void> encode(const data<Schema, FromEncoding>& from, data<Schema,encode::VtkLegacy>& to) { + int rc{}; + int ncid{}; + + rc = nc_create_mem("forstio_internal_write_memory", 0,/*NC_NETCDF4, */0, &ncid); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + + { + auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode_meta(from, ncid); + if(eov.is_error()){ + nc_close(ncid); + return eov; + } + } + + rc = nc_enddef(ncid); + if(rc != NC_NOERR){ + nc_close(ncid); + return make_error<err::critical>(); + } + + { + auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode(from, ncid); + if(eov.is_error()){ + nc_close(ncid); + return eov; + } + } + + NC_memio nc_memio; + rc = nc_close_memio(ncid, &nc_memio); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + + if(!nc_memio.memory || nc_memio.size == 0){ + return make_error<err::critical>(); + } + + try { + to.get_data().resize(nc_memio.size); + }catch(const std::exception& e){ + (void) e; + return make_error<err::out_of_memory>(); + } + + for(std::size_t i = 0; i < nc_memio.size; ++i){ + to.get_data().at(i) = static_cast<uint8_t*>(nc_memio.memory)[i]; + } + + free(nc_memio.memory); + nc_memio.memory = nullptr; + + return void_t{}; + } + + /** + * Decoder function + */ + template<typename ToEncoding> + error_or<void> decode(data<Schema, encode::VtkLegacy>& from_decode, data<Schema,ToEncoding>& to_decode) { + int ncid{}; + int rc{}; + + rc = nc_open_mem("forstio_internal_read_memory", NC_NOWRITE, from_decode.get_data().size(), &from_decode.get_data()[0], &ncid); + if(rc != NC_NOERR){ + // Don't know how to get the error, so fail critically. + return make_error<err::critical>(); + } + + auto eov = impl::netcdf_decode<Schema, ToEncoding>::decode(to_decode, ncid); + + nc_close(ncid); + + return eov; + } +}; +} diff --git a/modules/codec-vtk/c++/netcdf.tmpl.hpp b/modules/codec-vtk/c++/netcdf.tmpl.hpp new file mode 100644 index 0000000..bf257e4 --- /dev/null +++ b/modules/codec-vtk/c++/netcdf.tmpl.hpp @@ -0,0 +1,348 @@ +#pragma once + +namespace saw { +namespace impl { +template<typename Schema> +struct netcdf_primitive_id { + static_assert(always_false<Schema>, "Not a primitive id"); +}; + +template<> +struct netcdf_primitive_id<schema::Int32> { + static constexpr nc_type value = NC_INT; +}; + +template<> +struct netcdf_primitive_id<schema::UInt32> { + static constexpr nc_type value = NC_UINT; +}; + +template<> +struct netcdf_primitive_id<schema::Int64> { + static constexpr nc_type value = NC_INT64; +}; + +template<> +struct netcdf_primitive_id<schema::UInt64> { + static constexpr nc_type value = NC_UINT64; +}; + +template<> +struct netcdf_primitive_id<schema::Float32> { + static constexpr nc_type value = NC_FLOAT; +}; + +template<> +struct netcdf_primitive_id<schema::Float64> { + static constexpr nc_type value = NC_DOUBLE; +}; + +template<typename Schema> +struct netcdf_is_group { + static constexpr bool value = false; +}; + +template<typename... T, string_literal... Lits> +struct netcdf_is_group<schema::Struct<schema::Member<T,Lits>...>> { + static constexpr bool value = true; +}; + +template<typename Schema, typename ToEncode> +struct netcdf_encode; + +template<typename T, size_t N, typename ToEncode> +struct netcdf_encode<schema::Primitive<T,N>, ToEncode> { + using Schema = schema::Primitive<T,N>; + + static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + int rc{}; + + typename native_data_type<Schema>::type val = from.get(); + + rc = nc_put_var(ncid, ncvarid, &val); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + + return void_t{}; + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + (void) from; + (void) ncid; + (void) ncvarid; + return void_t{}; + } +}; + +template<typename T, size_t Dim, typename ToEncode> +struct netcdf_encode<schema::Array<T,Dim>, ToEncode> { + using Schema = schema::Array<T,Dim>; + + template<size_t Level> + static error_or<void> encode_level(data<Schema,ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } + + static error_or<void> encode(data<Schema, ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } +}; + +template<typename... T, string_literal... Lits, typename ToEncode> +struct netcdf_encode<schema::Struct<schema::Member<T,Lits>...>, ToEncode> { + using Schema = schema::Struct<schema::Member<T,Lits>...>; + + template<std::size_t i> + static error_or<void> encode_member(const data<Schema, ToEncode>& from, int ncid){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::value){ + return make_error<err::not_implemented>(); + }else{ + int nc_varid{}; + int rc {}; + rc = nc_inq_varid(ncid, Literal.data.data(), &nc_varid); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_encode<Type, ToEncode>::encode(from.template get<Literal>(), ncid, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = encode_member<i+1>(from, ncid); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid){ + if constexpr (sizeof...(T) > 0){ + auto eov = encode_member<0>(from, ncid); + return eov; + } + + return void_t{}; + } + + template<std::size_t i> + static error_or<void> encode_meta_member(const data<Schema, ToEncode>& from, int ncid){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::value){ + return make_error<err::not_implemented>(); + }else{ + int nc_varid{}; + int rc {}; + rc = nc_def_var(ncid, Literal.data.data(), netcdf_primitive_id<Type>::value, 0, nullptr, &nc_varid); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_encode<Type, ToEncode>::encode_meta(from.template get<Literal>(), ncid, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = encode_meta_member<i+1>(from, ncid); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid){ + if constexpr (sizeof...(T) > 0){ + auto eov = encode_meta_member<0>(from, ncid); + return eov; + } + + return void_t{}; + } +}; + +template<typename Schema, typename ToDecode> +struct netcdf_decode; + +template<typename T, size_t N, typename ToDecode> +struct netcdf_decode<schema::Primitive<T,N>, ToDecode> { + using Schema = schema::Primitive<T,N>; + + static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ + int rc{}; + + nc_type nc_vartype{}; + int nc_dimnum{}; + std::array<int,NC_MAX_VAR_DIMS> 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<err::critical>(); + } + if(nc_vartype != netcdf_primitive_id<schema::Primitive<T,N>>::value){ + return make_error<err::critical>(); + } + if(nc_dimnum != 0){ + return make_error<err::critical>(); + } + + typename native_data_type<schema::Primitive<T,N>>::type val{}; + rc = nc_get_var(from, nc_varid, &val); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + + to.set(val); + + return void_t {}; + } +}; + +template<typename T, size_t Dim, typename ToDecode> +struct netcdf_decode<schema::Array<T,Dim>, ToDecode> { + using Schema = schema::Array<T,Dim>; + + template<std::size_t Level> + static error_or<void> decode_level(data<Schema, ToDecode>& to, int from, int nc_varid, std::array<std::size_t, Dim>& index, const std::array<size_t,Dim>& count){ + if constexpr ( Level == Dim ){ + int rc{}; + typename native_data_type<T>::type val; + rc = nc_get_vara(from, nc_varid, index.data(), count.data(), &val); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + to.at(index).set(val); + }else{ + const std::size_t dim_size = to.get_dim_size(Level); + for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ + auto eov = decode_level<Level+1>(to, from, nc_varid, index, count); + if(eov.is_error()){ + return eov; + } + } + } + + return void_t{}; + } + + static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ + int rc{}; + + nc_type nc_vartype{}; + + int nc_dimnum{}; + std::array<int, NC_MAX_VAR_DIMS> 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<err::critical>(); + } + if(nc_vartype != netcdf_primitive_id<T>::value){ + return make_error<err::critical>(); + } + if(nc_dimnum != Dim){ + return make_error<err::critical>(); + } + + std::array<std::size_t, Dim> dims; + std::array<size_t, Dim> count; + for(std::size_t i = 0; i < Dim; ++i){ + rc = nc_inq_dim(from, nc_dimids[i], nullptr, &dims[i]); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + count[i] = 1; + } + + to = {dims}; + std::array<std::size_t, Dim> index; + + return decode_level<0>(to, from, nc_varid, index, count); + } +}; + +template<typename... T, string_literal... Lits, typename ToDecode> +struct netcdf_decode<schema::Struct<schema::Member<T,Lits>...>, ToDecode> { + using Schema = schema::Struct<schema::Member<T,Lits>...>; + + template<std::size_t i> + static error_or<void> decode_member(data<Schema,ToDecode>& to, int from){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::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<err::critical>(); + } + auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), 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<err::critical>(); + } + auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), from, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = decode_member<i+1>(to, from); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + + static error_or<void> decode(data<Schema, ToDecode>& to, int from){ + if constexpr (sizeof...(T) > 0){ + auto eov = decode_member<0>(to, from); + return eov; + } + + return void_t{}; + } +}; +} +} diff --git a/modules/codec-vtk/tests/SConscript b/modules/codec-vtk/tests/SConscript new file mode 100644 index 0000000..f8ffc92 --- /dev/null +++ b/modules/codec-vtk/tests/SConscript @@ -0,0 +1,31 @@ +#!/bin/false + +import os +import os.path +import glob + + +Import('env') + +dir_path = Dir('.').abspath + +# Environment for base library +test_cases_env = env.Clone(); + +test_cases_env.Append(LIBS=['forstio-test']); + +test_cases_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) +test_cases_env.headers = sorted(glob.glob(dir_path + "/*.hpp")) + +env.sources += test_cases_env.sources; +env.headers += test_cases_env.headers; + +objects_static = [] +test_cases_env.add_source_files(objects_static, test_cases_env.sources, shared=False); +test_cases_env.program = test_cases_env.Program('#bin/tests', [objects_static, env.library_static]); + +# Set Alias +env.Alias('test', test_cases_env.program); +env.Alias('check', test_cases_env.program); + +env.targets += ['test','check']; diff --git a/modules/codec-vtk/tests/codec-netcdf.cpp b/modules/codec-vtk/tests/codec-netcdf.cpp new file mode 100644 index 0000000..540f60e --- /dev/null +++ b/modules/codec-vtk/tests/codec-netcdf.cpp @@ -0,0 +1,104 @@ +#include <forstio/test/suite.hpp> +#include "../c++/netcdf.hpp" + +namespace { +namespace schema { +using namespace saw::schema; +using TestStruct = Struct< + Member<Int32, "data">, + Member<Float64, "other"> +>; + +using TestArrayStruct = Struct< + Member<Array<Int32,2>, "data"> +>; +} + +std::array<uint8_t,112> tests_data_primitive_nc = { + 0x43, 0x44, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, + 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x05, 0x6f, 0x74, 0x68, 0x65, + 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x05, 0x40, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +std::array<uint8_t,156> tests_data_array_nc = { + 0x43, 0x44, 0x46, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x78, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x79, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, + 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e +}; + +SAW_TEST("NetCDF Struct Primitive write"){ + using namespace saw; + + data<schema::TestStruct, encode::Native> native; + + native.template get<"data">().set(5); + native.template get<"other">().set(32.0); + + codec<schema::TestStruct, encode::Netcdf> codec; + + data<schema::TestStruct, encode::Netcdf> netcdf; + + auto eov = codec.encode(native, netcdf); + SAW_EXPECT(eov.is_value(), "Encoding failed"); + auto& nc_data = netcdf.get_data(); + SAW_EXPECT(nc_data.size() == tests_data_primitive_nc.size(), "Incorrect size"); + + for(std::size_t i = 0; i < nc_data.size(); ++i){ + SAW_EXPECT(nc_data.at(i) == tests_data_primitive_nc.at(i), "Incorrect Value"); + } +} + +SAW_TEST("NetCDF Struct Primitive read"){ + using namespace saw; + + data<schema::TestStruct, encode::Netcdf> netcdf{tests_data_primitive_nc}; + data<schema::TestStruct, encode::Native> native; + + codec<schema::TestStruct, encode::Netcdf> codec; + + auto eov = codec.decode(netcdf, native); + SAW_EXPECT(eov.is_value(), "Decoding failed"); + SAW_EXPECT(native.template get<"data">().get() == 5, "Int Value incorrect"); + SAW_EXPECT(native.template get<"other">().get() == 32.0, "Double Value incorrect"); +} + +SAW_TEST("NetCDF Struct Array read"){ + using namespace saw; + + data<schema::TestArrayStruct, encode::Netcdf> netcdf{tests_data_array_nc}; + + data<schema::TestArrayStruct, encode::Native> native; + + codec<schema::TestArrayStruct, encode::Netcdf> codec; + + auto eov = codec.decode(netcdf, native); + SAW_EXPECT(eov.is_value(), "Decoding failed"); + auto& arr = native.template get<"data">(); + SAW_EXPECT(arr.get_dim_size(0) == 5, "Incorrect dimension 0"); + SAW_EXPECT(arr.get_dim_size(1) == 3, "Incorrect dimension 1"); + + for(std::size_t i = 0; i < 5; ++i){ + for(std::size_t j = 0; j < 3; ++j){ + int64_t exp_val = i * 3 + j; + SAW_EXPECT(arr.at({i,j}).get() == exp_val, "Incorrect value"); + } + } +} +} |