@@ -109,10 +109,19 @@ RecordComponent &RecordComponent::resetDataset(Dataset d)
109109 throw error::WrongAPIUsage (
110110 " [RecordComponent] Must set specific datatype." );
111111 }
112- // if( d.extent.empty() )
113- // throw std::runtime_error("Dataset extent must be at least 1D.");
112+ if ( d.extent .empty ())
113+ throw std::runtime_error (" Dataset extent must be at least 1D." );
114114 if (d.empty ())
115+ {
116+ if (d.extent .empty ())
117+ {
118+ throw error::Internal (
119+ " A zero-dimensional dataset is not to be considered empty, but "
120+ " undefined. This is an internal safeguard against future "
121+ " changes that might not consider this." );
122+ }
115123 return makeEmpty (std::move (d));
124+ }
116125
117126 rc.m_isEmpty = false ;
118127 if (written ())
@@ -275,6 +284,13 @@ void RecordComponent::flush(
275284 {
276285 setUnitSI (1 );
277286 }
287+ auto constant_component_write_shape = [&]() {
288+ auto extent = getExtent ();
289+ return !extent.empty () &&
290+ std::none_of (extent.begin (), extent.end (), [](auto val) {
291+ return val == Dataset::JOINED_DIMENSION;
292+ });
293+ };
278294 if (!written ())
279295 {
280296 if (constant ())
@@ -294,16 +310,20 @@ void RecordComponent::flush(
294310 Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
295311 }
296312 IOHandler ()->enqueue (IOTask (this , aWrite));
297- aWrite.name = " shape" ;
298- Attribute a (getExtent ());
299- aWrite.dtype = a.dtype ;
300- aWrite.resource = a.getResource ();
301- if (isVBased)
313+ if (constant_component_write_shape ())
302314 {
303- aWrite.changesOverSteps = Parameter<
304- Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
315+
316+ aWrite.name = " shape" ;
317+ Attribute a (getExtent ());
318+ aWrite.dtype = a.dtype ;
319+ aWrite.resource = a.getResource ();
320+ if (isVBased)
321+ {
322+ aWrite.changesOverSteps = Parameter<
323+ Operation::WRITE_ATT>::ChangesOverSteps::IfPossible;
324+ }
325+ IOHandler ()->enqueue (IOTask (this , aWrite));
305326 }
306- IOHandler ()->enqueue (IOTask (this , aWrite));
307327 }
308328 else
309329 {
@@ -321,6 +341,13 @@ void RecordComponent::flush(
321341 {
322342 if (constant ())
323343 {
344+ if (!constant_component_write_shape ())
345+ {
346+ throw error::WrongAPIUsage (
347+ " Extended constant component from a previous shape to "
348+ " one that cannot be written (empty or with joined "
349+ " dimension)." );
350+ }
324351 bool isVBased = retrieveSeries ().iterationEncoding () ==
325352 IterationEncoding::variableBased;
326353 Parameter<Operation::WRITE_ATT> aWrite;
@@ -385,28 +412,35 @@ namespace
385412 };
386413} // namespace
387414
415+ inline void breakpoint ()
416+ {}
417+
388418void RecordComponent::readBase (bool require_unit_si)
389419{
390420 using DT = Datatype;
391- // auto & rc = get();
392- Parameter<Operation::READ_ATT> aRead;
421+ auto &rc = get ();
393422
394- if (constant () && !empty ())
395- {
396- aRead.name = " value" ;
397- IOHandler ()->enqueue (IOTask (this , aRead));
398- IOHandler ()->flush (internal::defaultFlushParams);
423+ readAttributes (ReadMode::FullyReread);
399424
400- Attribute a (*aRead.resource );
401- DT dtype = *aRead.dtype ;
425+ auto read_constant =
426+ [&]() // comment for forcing clang-format into putting a newline here
427+ {
428+ Attribute a = rc.readAttribute (" value" );
429+ DT dtype = a.dtype ;
402430 setWritten (false , Attributable::EnqueueAsynchronously::No);
403431 switchNonVectorType<MakeConstant>(dtype, *this , a);
404432 setWritten (true , Attributable::EnqueueAsynchronously::No);
405433
406- aRead.name = " shape" ;
407- IOHandler ()->enqueue (IOTask (this , aRead));
408- IOHandler ()->flush (internal::defaultFlushParams);
409- a = Attribute (*aRead.resource );
434+ if (!containsAttribute (" shape" ))
435+ {
436+ setWritten (false , Attributable::EnqueueAsynchronously::No);
437+ resetDataset (Dataset (dtype, {}));
438+ setWritten (true , Attributable::EnqueueAsynchronously::No);
439+
440+ return ;
441+ }
442+
443+ a = rc.attributes ().at (" shape" );
410444 Extent e;
411445
412446 // uint64_t check
@@ -416,7 +450,7 @@ void RecordComponent::readBase(bool require_unit_si)
416450 else
417451 {
418452 std::ostringstream oss;
419- oss << " Unexpected datatype (" << *aRead .dtype
453+ oss << " Unexpected datatype (" << a .dtype
420454 << " ) for attribute 'shape' (" << determineDatatype<uint64_t >()
421455 << " aka uint64_t)" ;
422456 throw error::ReadError (
@@ -429,9 +463,13 @@ void RecordComponent::readBase(bool require_unit_si)
429463 setWritten (false , Attributable::EnqueueAsynchronously::No);
430464 resetDataset (Dataset (dtype, e));
431465 setWritten (true , Attributable::EnqueueAsynchronously::No);
432- }
466+ };
433467
434- readAttributes (ReadMode::FullyReread);
468+ if (constant () && !empty ())
469+ {
470+ breakpoint ();
471+ read_constant ();
472+ }
435473
436474 if (require_unit_si)
437475 {
@@ -445,16 +483,17 @@ void RecordComponent::readBase(bool require_unit_si)
445483 " '" +
446484 myPath ().openPMDPath () + " '." );
447485 }
448- if (!getAttribute (" unitSI" ).getOptional <double >().has_value ())
486+ if (auto attr = getAttribute (" unitSI" );
487+ !attr.getOptional <double >().has_value ())
449488 {
450489 throw error::ReadError (
451490 error::AffectedObject::Attribute,
452491 error::Reason::UnexpectedContent,
453492 {},
454493 " Unexpected Attribute datatype for 'unitSI' (expected double, "
455494 " found " +
456- datatypeToString (Attribute (*aRead. resource ). dtype ) +
457- " ) in ' " + myPath ().openPMDPath () + " '." );
495+ datatypeToString (attr. dtype ) + " ) in ' " +
496+ myPath ().openPMDPath () + " '." );
458497 }
459498 }
460499}
0 commit comments