@@ -571,6 +571,36 @@ template <std::integral I> class Clustering {
571571 // Saving and Loading.
572572 static constexpr lib::Version save_version{0 , 0 , 0 };
573573 static constexpr std::string_view serialization_schema = " clustering" ;
574+
575+ lib::SaveTable metadata () const {
576+ return lib::SaveTable (
577+ serialization_schema,
578+ save_version,
579+ {{" integer_type" , lib::save (datatype_v<I>)},
580+ {" num_clusters" , lib::save (size ())}}
581+ );
582+ }
583+
584+ void save (std::ostream& os) const {
585+ for (const auto & [id, cluster] : *this ) {
586+ cluster.serialize (os);
587+ }
588+ }
589+
590+ static Clustering<I>
591+ load (const lib::ContextFreeLoadTable& table, std::istream& stream) {
592+ auto saved_integer_type = lib::load_at<DataType>(table, " integer_type" );
593+ if (saved_integer_type != datatype_v<I>) {
594+ throw ANNEXCEPTION (" Clustering was saved using {} but we're trying to reload it using {}!" , saved_integer_type, datatype_v<I>);
595+ }
596+ auto num_clusters = lib::load_at<size_t >(table, " num_clusters" );
597+ auto clustering = Clustering<I>();
598+ for (size_t i = 0 ; i < num_clusters; ++i) {
599+ clustering.insert (Cluster<I>::deserialize (stream));
600+ }
601+ return clustering;
602+ }
603+
574604 lib::SaveTable save (const lib::SaveContext& ctx) const {
575605 // Serialize all clusters into an auxiliary file.
576606 auto fullpath = ctx.generate_name (" clustering" , " bin" );
@@ -582,48 +612,28 @@ template <std::integral I> class Clustering {
582612 }
583613 }
584614
585- return lib::SaveTable (
586- serialization_schema,
587- save_version,
588- {{" filepath" , lib::save (fullpath.filename ())},
589- SVS_LIST_SAVE (filesize),
590- {" integer_type" , lib::save (datatype_v<I>)},
591- {" num_clusters" , lib::save (size ())}}
592- );
615+ auto table = metadata ();
616+ table.insert (" filepath" , lib::save (fullpath.filename ()));
617+ table.insert (" filesize" , lib::save (filesize));
618+ return table;
619+
620+ return table;
593621 }
594622
595623 static Clustering<I> load (const lib::LoadTable& table) {
596- // Ensure we have the correct integer type when decoding.
597- auto saved_integer_type = lib::load_at<DataType>( table, " integer_type " );
598- if (saved_integer_type != datatype_v<I>) {
599- auto type = datatype_v<I>;
624+ auto expected_filesize = lib::load_at< size_t >(table, " filesize " );
625+ auto file = table. resolve_at ( " filepath " );
626+ size_t actual_filesize = std::filesystem::file_size (file);
627+ if (actual_filesize != expected_filesize) {
600628 throw ANNEXCEPTION (
601- " Clustering was saved using {} but we're trying to reload it using {}!" ,
602- saved_integer_type ,
603- type
629+ " Expected cluster file size to be {}. Instead, it is {}!" ,
630+ actual_filesize ,
631+ expected_filesize
604632 );
605633 }
606634
607- auto num_clusters = lib::load_at<size_t >(table, " num_clusters" );
608- auto expected_filesize = lib::load_at<size_t >(table, " filesize" );
609- auto clustering = Clustering<I>();
610- {
611- auto file = table.resolve_at (" filepath" );
612- size_t actual_filesize = std::filesystem::file_size (file);
613- if (actual_filesize != expected_filesize) {
614- throw ANNEXCEPTION (
615- " Expected cluster file size to be {}. Instead, it is {}!" ,
616- actual_filesize,
617- expected_filesize
618- );
619- }
620-
621- auto io = lib::open_read (file);
622- for (size_t i = 0 ; i < num_clusters; ++i) {
623- clustering.insert (Cluster<I>::deserialize (io));
624- }
625- }
626- return clustering;
635+ auto io = lib::open_read (file);
636+ return load (table, io);
627637 }
628638
629639 private:
0 commit comments