diff --git a/Control/AthContainers/AthContainers/PackedLink.h b/Control/AthContainers/AthContainers/PackedLink.h
index daee0ae1c683ab2e7a900ac592012ac7dca30a5a..ddd07a7ac1f5007e9875e39b1be68608005ef4f8 100644
--- a/Control/AthContainers/AthContainers/PackedLink.h
+++ b/Control/AthContainers/AthContainers/PackedLink.h
@@ -21,6 +21,7 @@
 #include "AthContainers/tools/PackedLinkVectorFactory.h"
 #include "AthContainers/PackedLinkConstAccessor.h"
 #include "AthContainers/PackedLinkAccessor.h"
+#include "AthContainers/PackedLinkDecorator.h"
 
 
 #endif // not ATHCONTAINERS_PACKEDLINK_H
diff --git a/Control/AthContainers/AthContainers/PackedLinkDecorator.h b/Control/AthContainers/AthContainers/PackedLinkDecorator.h
new file mode 100644
index 0000000000000000000000000000000000000000..32a7c97709d7fa332090dcc570493f5a13f8a629
--- /dev/null
+++ b/Control/AthContainers/AthContainers/PackedLinkDecorator.h
@@ -0,0 +1,695 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/*
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file AthContainers/PackedLinkDecorator.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2023
+ * @brief Helper class to provide type-safe access to aux data,
+ *        specialized for @c PackedLink.
+ */
+
+
+#ifndef ATHCONTAINERS_PACKEDLINKDECORATOR_H
+#define ATHCONTAINERS_PACKEDLINKDECORATOR_H
+
+
+#include "AthContainersInterfaces/AuxTypes.h"
+#include "AthContainersInterfaces/IAuxElement.h"
+#include "AthContainers/Accessor.h"
+#include "AthContainers/PackedLinkConstAccessor.h"
+#include "AthContainers/PackedLink.h"
+#include "AthContainers/AuxVectorData.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainers/tools/ELProxy.h"
+#include "AthContainers/tools/AuxDataTraits.h"
+#include "AthContainers/tools/AuxElementConcepts.h"
+#include "AthLinks/DataLink.h"
+#include "CxxUtils/concepts.h"
+#include "CxxUtils/checker_macros.h"
+#include <string>
+#include <typeinfo>
+#include <iterator>
+
+
+namespace SG {
+
+
+/**
+ * @brief Helper class to provide type-safe access to aux data,
+ *        specialized for PackedLink.
+ *
+ * This is a version of @c Decorator, specialized for packed links.
+ *
+ * This is like @c Accessor, except that it only `decorates' the container.
+ * What this means is that this object can operate on a const container
+ * and return a non-const reference.  However, if the container is locked,
+ * this will only work if either this is a reference to a new variable,
+ * in which case it is marked as a decoration, or it is a reference
+ * to a variable already marked as a decoration.
+ *
+ * Although the type argument is @c PackedLink<CONT>, the objects that
+ * this accessor produces are @c ElementLink<CONT> (returned by value
+ * rather than by const reference).  The @c getDataSpan method will
+ * then produce a (writable) span over @c ElementLink<CONT>.
+ * (There are separate methods for returning spans over the
+ * PackedLink/DataLink arrays themselves.)
+ *
+ * You might use this something like this:
+ *
+ *@code
+ *   // Only need to do this once.
+ *   using Cont_t = std::vector<int>;
+ *   static const SG::Decorator<SG::PackedLink<Cont_t> links ("links");
+ *   ...
+ *   const DataVector<MyClass>* v = ...;
+ *   const Myclass* m = v->at(2);
+ *   links (*m) = ElementLink<Cont_t> (...);
+ *   auto span = links.getDataSpan (*v);
+ *   span[2] = ElementLink<Cont_t> (...);
+ @endcode
+*/
+template <class CONT, class ALLOC>
+class Decorator<PackedLink<CONT>, ALLOC>
+  : public detail::LinkedVarAccessorBase
+{
+public:
+  // Aliases for the types we're dealing with.
+  using Link_t = ElementLink<CONT>;
+  using PLink_t = SG::PackedLink<CONT>;
+  using DLink_t = DataLink<CONT>;
+  using DLinkAlloc_t = typename std::allocator_traits<ALLOC>::template rebind_alloc<DLink_t>;
+
+
+  /// Spans over the objects that are actually stored.
+  using const_PackedLink_span = typename AuxDataTraits<PackedLink<CONT>, ALLOC>::const_span;
+  using const_DataLink_span = typename AuxDataTraits<DataLink<CONT>, DLinkAlloc_t>::const_span;
+  using PackedLink_span = typename AuxDataTraits<PackedLink<CONT>, ALLOC>::span;
+  using DataLink_span = typename AuxDataTraits<DataLink<CONT>, DLinkAlloc_t>::span;
+
+
+  /// Converter from @c PackedLink -> @c ElementLink.
+  using ConstConverter_t = detail::PackedLinkConstConverter<CONT>;
+
+
+  /// Transform a span over @c PackedLink to a span over @c ElementLink.
+  using const_span =
+    CxxUtils::transform_view_with_at<const_PackedLink_span, ConstConverter_t>;
+
+
+  /// Writable proxy for @c PackedLink appearing like an @c ElementLink.
+  using ELProxy = detail::ELProxyT<detail::ELProxyValBase<CONT> >;
+
+
+  /// Transform a non-const span of @c PackedLink to a range
+  /// of @c ElementLink proxies.
+  using span = CxxUtils::transform_view_with_at<PackedLink_span,
+                                                detail::ELProxyInSpanConverter<CONT> >;
+
+
+  /// Type the user sees.
+  using element_type = Link_t;
+
+  /// Type referencing an item.
+  using reference_type = ELProxy;
+
+  /// Not supported.
+  using container_pointer_type = void;
+  using const_container_pointer_type = void;
+
+
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name);
+
+
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   * @param clsname The name of its associated class.  May be blank.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name, const std::string& clsname);
+
+
+  /**
+   * @brief Constructor taking an auxid directly.
+   * @param auxid ID for this auxiliary variable.
+   *
+   * Will throw @c SG::ExcAuxTypeMismatch if the types don't match.
+   */
+  Decorator (const SG::auxid_t auxid);
+
+
+  /**
+   * @brief Fetch the variable for one element.
+   * @param e The element for which to fetch the variable.
+   *
+   * Will return an @c ElementLink proxy, which may be converted to
+   * or assigned from an @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  template <IsConstAuxElement ELT>
+  ELProxy operator() (const ELT& e) const;
+
+
+  /**
+   * @brief Fetch the variable for one element.
+   * @param container The container from which to fetch the variable.
+   * @param index The index of the desired element.
+   *
+   * This allows retrieving aux data by container / index.
+   *
+   * Will return an @c ElementLink proxy, which may be converted to
+   * or assigned from an @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  ELProxy
+  operator() (const AuxVectorData& container, size_t index) const;
+
+
+  /**
+   * @brief Set the variable for one element.
+   * @param e The element for which to set the variable.
+   * @param l The @c ElementLink to set.
+   */
+  template <IsConstAuxElement ELT>
+  void set (const ELT& e, const element_type& l) const;
+
+
+  /**
+   * @brief Set the variable for one element.
+   * @param container The container for which to set the variable.
+   * @param index The index of the desired element.
+   * @param l The @c ElementLink to set.
+   */
+  void set (const AuxVectorData& container, size_t index, const Link_t& x) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the array of @c PackedLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const PLink_t*
+  getPackedLinkArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the linked array of @c DataLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const DLink_t*
+  getDataLinkArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the array of @c PackedLinks,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  PLink_t*
+  getPackedLinkDecorArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the linked array of @c DataLinks,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  DLink_t*
+  getDataLinkDecorArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c PackedLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_PackedLink_span
+  getPackedLinkSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c DataLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_DataLink_span
+  getDataLinkSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span of @c ElementLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_span
+  getDataSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c PackedLinks, as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  PackedLink_span
+  getPackedLinkDecorSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c DataLinks, as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  DataLink_span
+  getDataLinkDecorSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span of @c ElementLink proxies, as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * The proxies may be converted to or assigned from @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  span
+  getDecorationSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Test to see if this variable exists in the store and is writable.
+   * @param e An element of the container which to test the variable.
+   */
+  template <IsConstAuxElement ELT>
+  bool isAvailableWritable (const ELT& e) const;
+
+
+protected:
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   * @param clsname The name of its associated class.  May be blank.
+   * @param flags Optional flags qualifying the type.  See AuxTypeRegsitry.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name,
+             const std::string& clsname,
+             const SG::AuxVarFlags flags);
+};
+
+
+//************************************************************************
+
+
+/**
+ * @brief Helper class to provide constant type-safe access to aux data,
+ *        specialized for a vector of PackedLink.
+ *
+ * This is like @c Accessor, except that it only `decorates' the container.
+ * What this means is that this object can operate on a const container
+ * and return a non-const reference.  However, if the container is locked,
+ * this will only work if either this is a reference to a new variable,
+ * in which case it is marked as a decoration, or it is a reference
+ * to a variable already marked as a decoration.
+ *
+ * Although the type argument is @c PackedLink<CONT>, the objects that
+ * this accessor produces are @c ElementLink<CONT> (returned by value
+ * rather than by const reference).  The @c getDataSpan method will
+ * then produce a (writable) span over @c ElementLink<CONT>.
+ * (There are separate methods for returning spans over the
+ * PackedLink/DataLink arrays themselves.)
+ *
+ * You might use this something like this:
+ *
+ *@code
+ *   // Only need to do this once.
+ *   using Cont_t = std::vector<int>;
+ *   static const SG::Decorator<std::vector<SG::PackedLink<Cont_t> > links ("links");
+ *   ...
+ *   const DataVector<MyClass>* v = ...;
+ *   const Myclass* m = v->at(2);
+ *   links (*m).push_back (ElementLink<Cont_t> (...));
+ *   auto span = links.getDataSpan (*v);
+ *   span[2][1] = ElementLink<Cont_t> (...);
+ @endcode
+ *
+ * You can also use this to define getters/setters in your class:
+ *
+ *@code
+ *  class Myclass {
+ *    ...
+ *    auto get_links() const
+ *    { const static ConstAccessor<SG::PackedLink<Cont_t> > acc ("links");
+ *      return acc (*this); }
+ *    void set_links (const std::vector<ElementLink<Cont_t> >& elv)
+ *    { const static Accessor<std::vector<SG::PackedLink<Cont_t> > > acc ("links");
+ *      acc (*this) = elv; }
+ @endcode
+*/
+template <class CONT, class ALLOC, class VALLOC>
+class Decorator<std::vector<PackedLink<CONT>, VALLOC>, ALLOC>
+  : public detail::LinkedVarAccessorBase
+{
+public:
+  // Aliases for the types we're dealing with.
+  using Link_t = ElementLink<CONT>;
+  using PLink_t = SG::PackedLink<CONT>;
+  using VElt_t = std::vector<SG::PackedLink<CONT>, VALLOC>;
+  using DLink_t = DataLink<CONT>;
+  using DLinkAlloc_t = typename std::allocator_traits<ALLOC>::template rebind_alloc<DLink_t>;
+
+  /// Spans over the objects that are actually stored.
+  using const_PackedLinkVector_span = typename AuxDataTraits<VElt_t, ALLOC>::const_span;
+  using const_DataLink_span = typename AuxDataTraits<DataLink<CONT>, DLinkAlloc_t>::const_span;
+  using PackedLinkVector_span = typename AuxDataTraits<VElt_t, ALLOC>::span;
+  using DataLink_span = typename AuxDataTraits<DataLink<CONT>, DLinkAlloc_t>::span;
+
+  /// And spans over @c PackedLink objects.
+  using const_PackedLink_span = typename AuxDataTraits<PackedLink<CONT>, VALLOC>::const_span;
+  using PackedLink_span = typename AuxDataTraits<PackedLink<CONT>, VALLOC>::span;
+
+
+  /// Converter from vector of @c PackedLink to a span over @c ElementLinks.
+  using ConstVectorTransform_t = detail::PackedLinkVectorConstConverter<CONT>;
+
+  /// Transform a span over vector of @c PackedLink to a
+  /// span over span over @c ElementLink.
+  using const_span =
+    CxxUtils::transform_view_with_at<const_PackedLinkVector_span, ConstVectorTransform_t>;
+
+
+  /// Presents a vector of @c PackedLink as a range of @c ElementLink proxies.
+  using elt_span = detail::ELSpanProxy<CONT, VALLOC>;
+
+
+  /// Transform a span over vector of @c PackedLink to a
+  /// span over span over @c ElementLink proxies.
+  using ELSpanConverter = detail::ELSpanConverter<CONT, VALLOC>;
+  using span =
+    CxxUtils::transform_view_with_at<PackedLinkVector_span, ELSpanConverter >;
+
+
+  /// Type the user sees.
+  using element_type = elt_span;
+
+  /// Type referencing an item.
+  using reference_type = elt_span;
+
+  /// Not supported.
+  using container_pointer_type = void;
+  using const_container_pointer_type = void;
+
+
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name);
+
+
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   * @param clsname The name of its associated class.  May be blank.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name, const std::string& clsname);
+
+
+  /**
+   * @brief Constructor taking an auxid directly.
+   * @param auxid ID for this auxiliary variable.
+   *
+   * Will throw @c SG::ExcAuxTypeMismatch if the types don't match.
+   */
+  Decorator (const SG::auxid_t auxid);
+
+
+  /**
+   * @brief Fetch the variable for one element.
+   * @param e The element for which to fetch the variable.
+   *
+   * This will return a range of @c ElementLink proxies.
+   * These proxies may be converted to or assigned from @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  template <IsConstAuxElement ELT>
+  elt_span operator() (const ELT& e) const;
+
+
+  /**
+   * @brief Fetch the variable for one element.
+   * @param container The container from which to fetch the variable.
+   * @param index The index of the desired element.
+   *
+   * This allows retrieving aux data by container / index.
+   *
+   * This will return a range of @c ElementLink proxies.
+   * These proxies may be converted to or assigned from @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  elt_span
+  operator() (const AuxVectorData& container, size_t index) const;
+
+
+  /**
+   * @brief Set the variable for one element.
+   * @param e The element for which to set the variable.
+   * @param r The variable value to set, as a range over @c ElementLink.
+   */
+  template <IsConstAuxElement ELT, detail::ElementLinkRange<CONT> RANGE>
+  void set (const ELT& e, const RANGE& x) const;
+
+
+  /**
+   * @brief Set the variable for one element.
+   * @param container The container for which to set the variable.
+   * @param index The index of the desired element.
+   * @param r The variable value to set, as a range over @c ElementLink.
+   */
+  template <detail::ElementLinkRange<CONT> RANGE>
+  void set (const AuxVectorData& container, size_t index, const RANGE& r) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the array of vectors of @c PackedLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const VElt_t*
+  getPackedLinkVectorArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the linked array of @c DataLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const DLink_t*
+  getDataLinkArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the array of vectors of @c PackedLinks,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   */
+  VElt_t*
+  getPackedLinkVectorDecorArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a pointer to the start of the linked array of @c DataLinks,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   */
+  DLink_t*
+  getDataLinkDecorArray (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the vector of @c PackedLinks for a given element.
+   * @param e The element for which to fetch the variable.
+   */
+  template <IsConstAuxElement ELT>
+  const_PackedLink_span
+  getPackedLinkSpan (const ELT& e) const;
+
+
+  /**
+   * @brief Get a span over the vector of @c PackedLinks for a given element.
+   * @param container The container from which to fetch the variable.
+   * @param index The index of the desired element.
+   */
+  const_PackedLink_span
+  getPackedLinkSpan (const AuxVectorData& container, size_t index) const;
+
+
+  /**
+   * @brief Get a span over the vector of @c PackedLinks for a given element.
+   * @param container The container from which to fetch the variable.
+   * @param index The index of the desired element.
+   */
+  PackedLink_span
+  getPackedLinkSpan (AuxVectorData& container, size_t index) const;
+
+
+  /**
+   * @brief Get a span over the vectors of @c PackedLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_PackedLinkVector_span
+  getPackedLinkVectorSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c DataLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_DataLink_span
+  getDataLinkSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over spans of @c ElementLinks.
+   * @param container The container from which to fetch the variable.
+   */
+  const_span
+  getDataSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the vector of @c PackedLinks for a given element,
+   *        as a decoration.
+   * @param e The element for which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  template <IsConstAuxElement ELT>
+  PackedLink_span
+  getPackedLinkDecorSpan (const ELT& e) const;
+
+
+  /**
+   * @brief Get a span over the vector of @c PackedLinks for a given element,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   * @param index The index of the desired element.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  PackedLink_span
+  getPackedLinkDecorSpan (const AuxVectorData& container, size_t index) const;
+
+
+  /**
+   * @brief Get a span over the vectors of @c PackedLinks,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  PackedLinkVector_span
+  getPackedLinkVectorDecorSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over the array of @c DataLinks, as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  DataLink_span
+  getDataLinkDecorSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Get a span over spans of @c ElementLink proxies,
+   *        as a decoration.
+   * @param container The container from which to fetch the variable.
+   *
+   * The individual proxies may be converted to or assigned from @c ElementLink.
+   * Each element may also be assigned from a range of @c ElementLink,
+   * or converted to a vector of @c ElementLink.
+   *
+   * If the container is locked, this will allow fetching only variables
+   * that do not yet exist (in which case they will be marked as decorations)
+   * or variables already marked as decorations.
+   */
+  span
+  getDecorationSpan (const AuxVectorData& container) const;
+
+
+  /**
+   * @brief Test to see if this variable exists in the store and is writable.
+   * @param e An element of the container which to test the variable.
+   */
+  template <IsConstAuxElement ELT>
+  bool isAvailableWritable (const ELT& e) const;
+
+
+protected:
+  /**
+   * @brief Constructor.
+   * @param name Name of this aux variable.
+   * @param clsname The name of its associated class.  May be blank.
+   * @param flags Optional flags qualifying the type.  See AuxTypeRegsitry.
+   *
+   * The name -> auxid lookup is done here.
+   */
+  Decorator (const std::string& name,
+             const std::string& clsname,
+             const SG::AuxVarFlags flags);
+};
+
+
+} // namespace SG
+
+
+#include "AthContainers/PackedLinkDecorator.icc"
+
+
+
+#endif // not ATHCONTAINERS_PACKEDLINKDECORATOR_H
diff --git a/Control/AthContainers/AthContainers/PackedLinkDecorator.icc b/Control/AthContainers/AthContainers/PackedLinkDecorator.icc
new file mode 100644
index 0000000000000000000000000000000000000000..3d04e4565af5b1f83f5875ba12df22c2aa3c6c17
--- /dev/null
+++ b/Control/AthContainers/AthContainers/PackedLinkDecorator.icc
@@ -0,0 +1,836 @@
+/*
+ * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file PackedLinkDecorator.icc
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Nov, 2023
+ * @brief Helper class to provide type-safe access to aux data,
+ *        specialized for @c PackedLink.
+ */
+
+#include "AthContainers/AuxElement.h"
+#include "AthContainers/AuxTypeRegistry.h"
+#include "AthContainers/exceptions.h"
+
+
+namespace SG {
+
+
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC>
+inline
+Decorator<PackedLink<CONT>, ALLOC>::Decorator (const std::string& name)
+  : Decorator (name, "", SG::AuxVarFlags::None)
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ * @param clsname The name of its associated class.  May be blank.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC>
+inline
+Decorator<PackedLink<CONT>, ALLOC>::Decorator (const std::string& name,
+                                               const std::string& clsname)
+  : Decorator (name, clsname, SG::AuxVarFlags::None)
+{
+}
+
+
+/**
+ * @brief Constructor taking an auxid directly.
+ * @param auxid ID for this auxiliary variable.
+ *
+ * Will throw @c SG::ExcAuxTypeMismatch if the types don't match.
+ */
+template <class CONT, class ALLOC>
+inline
+Decorator<PackedLink<CONT>, ALLOC>::Decorator (const SG::auxid_t auxid)
+{
+  AuxTypeRegistry& r = AuxTypeRegistry::instance();
+  m_auxid = auxid;
+  r.checkAuxID<PLink_t, ALLOC> (m_auxid);
+  m_linkedAuxid = r.linkedVariable (m_auxid);
+  if (m_linkedAuxid == static_cast<uint32_t>(null_auxid)) {
+    throw SG::ExcNoLinkedVar (auxid, typeid (CONT));
+    // cppcheck-suppress missingReturn; false positive
+  }
+}
+
+
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ * @param clsname The name of its associated class.  May be blank.
+ * @param flags Optional flags qualifying the type.  See AuxTypeRegsitry.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC>
+inline
+Decorator<PackedLink<CONT>, ALLOC>::Decorator
+  (const std::string& name,
+   const std::string& clsname,
+   const SG::AuxVarFlags flags)
+{
+  AuxTypeRegistry& r = AuxTypeRegistry::instance();
+  m_linkedAuxid = r.getAuxID<DLink_t, DLinkAlloc_t> (AuxTypeRegistry::linkedName (name),
+                                                     clsname,
+                                                     flags | AuxVarFlags::Linked);
+  m_auxid = r.getAuxID<PLink_t, ALLOC> (name, clsname, flags, m_linkedAuxid);
+}
+
+
+/**
+ * @brief Fetch the variable for one element.
+ * @param e The element for which to fetch the variable.
+ *
+ * Will return an @c ElementLink proxy, which may be converted to
+ * or assigned from an @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+template <IsConstAuxElement ELT>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::operator() (const ELT& e) const -> ELProxy
+{
+  assert (e.container() != 0);
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (*e.container());
+  return ELProxy (e.container()->template getDecoration<PLink_t> (this->m_auxid, e.index()),
+                  container_nc,
+                  this->m_auxid,
+                  this->m_linkedAuxid);
+}
+
+
+/**
+ * @brief Fetch the variable for one element.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ *
+ * This allows retrieving aux data by container / index.
+ *
+ * Will return an @c ElementLink proxy, which may be converted to
+ * or assigned from an @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::operator() (const AuxVectorData& container,
+                                                size_t index) const
+  -> ELProxy
+{
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (container);
+  return ELProxy (container.template getDecoration<PLink_t> (this->m_auxid, index),
+                  container_nc, this->m_auxid, this->m_linkedAuxid);
+}
+
+
+/**
+ * @brief Set the variable for one element.
+ * @param e The element for which to set the variable.
+ * @param l The @c ElementLink to set.
+ */
+template <class CONT, class ALLOC>
+template <IsConstAuxElement ELT>
+inline
+void Decorator<PackedLink<CONT>, ALLOC>::set (const ELT& e,
+                                              const Link_t& l) const
+{
+  set (*e.container(), e.index(), l);
+}
+
+
+/**
+ * @brief Set the variable for one element.
+ * @param container The container for which to set the variable.
+ * @param index The index of the desired element.
+ * @param l The @c ElementLink to set.
+ */
+template <class CONT, class ALLOC>
+inline
+void Decorator<PackedLink<CONT>, ALLOC>::set (const AuxVectorData& container,
+                                              size_t index,
+                                              const Link_t& l) const
+{
+  // Have to do this before creating the converter.
+  PLink_t& ll = container.template getDecoration<PLink_t> (this->m_auxid, index);
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (container);
+  detail::PackedLinkConverter<CONT> cnv (container_nc,
+                                         this->m_auxid,
+                                         this->m_linkedAuxid);
+  cnv.set (ll, l);
+}
+
+
+/**
+ * @brief Get a pointer to the start of the array of @c PackedLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getPackedLinkArray (const AuxVectorData& container) const
+  -> const PLink_t*
+{
+  return reinterpret_cast<const PLink_t*> (container.getDataArray (m_auxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the linked array of @c DataLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDataLinkArray (const AuxVectorData& container) const
+  -> const DLink_t*
+{
+  return reinterpret_cast<const DLink_t*>
+    (container.getDataArray (m_linkedAuxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the array of @c PackedLinks,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getPackedLinkDecorArray (const AuxVectorData& container) const
+  -> PLink_t*
+{
+  return reinterpret_cast<PLink_t*> (container.getDecorationArray (m_auxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the linked array of @c DataLinks,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDataLinkDecorArray (const AuxVectorData& container) const
+  -> DLink_t*
+{
+  return reinterpret_cast<DLink_t*> (container.getDecorationArray (m_linkedAuxid));
+}
+
+
+/**
+ * @brief Get a span over the array of @c PackedLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getPackedLinkSpan (const AuxVectorData& container) const
+  -> const_PackedLink_span
+{
+  auto beg = reinterpret_cast<const PLink_t*>(container.getDataArray (m_auxid));
+  return const_PackedLink_span (beg, container.size_v());
+}
+
+
+/**
+ * @brief Get a span over the array of @c DataLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDataLinkSpan (const AuxVectorData& container) const
+  -> const_DataLink_span
+{
+  const AuxDataSpanBase* sp = container.getDataSpan (m_linkedAuxid);
+  return const_DataLink_span (reinterpret_cast<const DLink_t*>(sp->beg),
+                              sp->size);
+}
+
+
+/**
+ * @brief Get a span of @c ElementLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDataSpan (const AuxVectorData& container) const
+  -> const_span
+{
+  return const_span (getPackedLinkSpan(container),
+                     ConstConverter_t (*container.getDataSpan (m_linkedAuxid)));
+}
+
+
+/**
+ * @brief Get a span over the array of @c PackedLinks, as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getPackedLinkDecorSpan (const AuxVectorData& container) const
+  -> PackedLink_span
+{
+  auto beg = reinterpret_cast<PLink_t*>
+    (container.getDecorationArray (this->m_auxid));
+  return PackedLink_span (beg, container.size_v());
+}
+
+
+/**
+ * @brief Get a span over the array of @c DataLinks, as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDataLinkDecorSpan (const AuxVectorData& container) const
+  -> DataLink_span
+{
+  (void)container.getDecorationArray (this->m_linkedAuxid); // check for locking
+  const AuxDataSpanBase* sp = container.getDataSpan (m_linkedAuxid);
+  return DataLink_span (reinterpret_cast<DLink_t*>(sp->beg), sp->size);
+}
+
+
+/**
+ * @brief Get a span of @c ElementLink proxies, as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * The proxies may be converted to or assigned from @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC>
+inline
+auto
+Decorator<PackedLink<CONT>, ALLOC>::getDecorationSpan (const AuxVectorData& container) const
+  -> span
+{
+  PackedLink_span pspan = getPackedLinkDecorSpan(container);
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (container);
+  return span (pspan,
+               detail::PackedLinkConverter<CONT> (container_nc,
+                                                  this->m_auxid,
+                                                  this->m_linkedAuxid));
+}
+
+
+/**
+ * @brief Test to see if this variable exists in the store and is writable.
+ * @param e An element of the container which to test the variable.
+ */
+template <class CONT, class ALLOC>
+template <IsConstAuxElement ELT>
+inline
+bool
+Decorator<PackedLink<CONT>, ALLOC>::isAvailableWritable (const ELT& e) const
+{
+  return e.container() &&
+    e.container()->isAvailableWritableAsDecoration (m_auxid) &&
+    e.container()->isAvailableWritableAsDecoration (m_linkedAuxid);
+}
+
+
+//************************************************************************
+
+
+// To make the declarations a bit more readable.
+#define DECORATOR Decorator<std::vector<PackedLink<CONT>, VALLOC>, ALLOC>
+
+
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+DECORATOR::Decorator (const std::string& name)
+  : Decorator (name, "", SG::AuxVarFlags::None)
+{
+}
+
+
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ * @param clsname The name of its associated class.  May be blank.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+DECORATOR::Decorator (const std::string& name,
+                      const std::string& clsname)
+  : Decorator (name, clsname, SG::AuxVarFlags::None)
+{
+}
+
+
+/**
+ * @brief Constructor taking an auxid directly.
+ * @param auxid ID for this auxiliary variable.
+ *
+ * Will throw @c SG::ExcAuxTypeMismatch if the types don't match.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+DECORATOR::Decorator (const SG::auxid_t auxid)
+{
+  AuxTypeRegistry& r = AuxTypeRegistry::instance();
+  m_auxid = auxid;
+  r.checkAuxID<VElt_t, ALLOC> (m_auxid);
+  m_linkedAuxid = r.linkedVariable (m_auxid);
+  if (m_linkedAuxid == static_cast<uint32_t>(null_auxid)) {
+    throw SG::ExcNoLinkedVar (auxid, typeid (CONT));
+  }
+}
+/**
+ * @brief Constructor.
+ * @param name Name of this aux variable.
+ * @param clsname The name of its associated class.  May be blank.
+ * @param flags Optional flags qualifying the type.  See AuxTypeRegsitry.
+ *
+ * The name -> auxid lookup is done here.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+DECORATOR::Decorator (const std::string& name,
+                      const std::string& clsname,
+                      const SG::AuxVarFlags flags)
+{
+  AuxTypeRegistry& r = AuxTypeRegistry::instance();
+  m_linkedAuxid = r.getAuxID<DLink_t, DLinkAlloc_t> (AuxTypeRegistry::linkedName (name),
+                                                     clsname,
+                                                     flags | AuxVarFlags::Linked);
+  m_auxid = r.getAuxID<VElt_t, ALLOC> (name, clsname, flags, m_linkedAuxid);
+}
+
+
+/**
+ * @brief Fetch the variable for one element.
+ * @param e The element for which to fetch the variable.
+ *
+ * This will return a range of @c ElementLink proxies.
+ * These proxies may be converted to or assigned from @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <IsConstAuxElement ELT>
+auto
+DECORATOR::operator() (const ELT& e) const
+  -> elt_span
+{
+  assert (e.container() != 0);
+  // This has be to called before making the ELSpanProxyHelper.
+  VElt_t* veltArr = getPackedLinkVectorDecorArray(*e.container());
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = *const_cast<AuxVectorData*>(e.container());
+  return elt_span (veltArr[e.index()], container_nc,
+                   this->m_auxid,
+                   this->m_linkedAuxid);
+}
+
+
+/**
+ * @brief Fetch the variable for one element.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ *
+ * This allows retrieving aux data by container / index.
+ *
+ * This will return a range of @c ElementLink proxies.
+ * These proxies may be converted to or assigned from @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+auto
+DECORATOR::operator() (const AuxVectorData& container,
+                       size_t index) const
+  -> elt_span
+{
+  // This has be to called before making the ELSpanProxyHelper.
+  VElt_t* veltArr = getPackedLinkVectorDecorArray(container);
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&>(container);
+  return elt_span (veltArr[index], container_nc,
+                   this->m_auxid,
+                   this->m_linkedAuxid);
+}
+
+
+/**
+ * @brief Set the variable for one element.
+ * @param e The element for which to set the variable.
+ * @param r The variable value to set, as a range over @c ElementLink.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <IsConstAuxElement ELT, detail::ElementLinkRange<CONT> RANGE>
+void DECORATOR::set (const ELT& e, const RANGE& r) const
+{
+  set (*e.container(), e.index(), r);
+}
+
+
+/**
+ * @brief Set the variable for one element.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ * @param r The variable value to set, as a range over @c ElementLink.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <detail::ElementLinkRange<CONT> RANGE>
+void DECORATOR::set (const AuxVectorData& container,
+                     size_t index,
+                     const RANGE& r) const
+{
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (container);
+  detail::PackedLinkConverter<CONT> cnv (container_nc,
+                                         this->m_auxid,
+                                         this->m_linkedAuxid);
+  VElt_t& velt = container.template getDecoration<VElt_t> (this->m_auxid, index);
+  cnv.set (velt, r);
+}
+
+
+/**
+ * @brief Get a pointer to the start of the array of vectors of @c PackedLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkVectorArray (const AuxVectorData& container) const
+  -> const VElt_t*
+{
+  return reinterpret_cast<const VElt_t*>
+    (container.getDataArray (m_auxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the linked array of @c DataLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDataLinkArray (const AuxVectorData& container) const
+  -> const DLink_t*
+{
+  return reinterpret_cast<const DLink_t*>
+    (container.getDataArray (m_linkedAuxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the array of vectors of @c PackedLinks,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkVectorDecorArray (const AuxVectorData& container) const
+  -> VElt_t*
+{
+  return reinterpret_cast<VElt_t*> (container.getDecorationArray (m_auxid));
+}
+
+
+/**
+ * @brief Get a pointer to the start of the linked array of @c DataLinks,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDataLinkDecorArray (const AuxVectorData& container) const
+  -> DLink_t*
+{
+  return reinterpret_cast<DLink_t*> (container.getDecorationArray (m_linkedAuxid));
+}
+
+
+/**
+ * @brief Get a span over the vector of @c PackedLinks for a given element.
+ * @param e The element for which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <IsConstAuxElement ELT>
+inline
+auto
+DECORATOR::getPackedLinkSpan (const ELT& e) const
+  -> const_PackedLink_span
+{
+  auto elt = reinterpret_cast<const VElt_t*>
+    (e.container()->getDataArray (this->m_auxid)) + e.index();
+  return const_PackedLink_span (elt->data(), elt->size());
+}
+
+
+/**
+ * @brief Get a span over the vector of @c PackedLinks for a given element.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkSpan (const AuxVectorData& container, size_t index) const
+  -> const_PackedLink_span
+{
+  auto elt = reinterpret_cast<const VElt_t*>
+    (container.getDataArray (this->m_auxid)) + index;
+  return const_PackedLink_span (elt->data(), elt->size());
+}
+
+
+/**
+ * @brief Get a span over the vector of @c PackedLinks for a given element.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkSpan (AuxVectorData& container, size_t index) const
+  -> PackedLink_span
+{
+  auto elt = reinterpret_cast<VElt_t*>
+    (container.getDataArray (this->m_auxid)) + index;
+  return PackedLink_span (elt->data(), elt->size());
+}
+
+
+/**
+ * @brief Get a span over the vectors of @c PackedLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkVectorSpan (const AuxVectorData& container) const
+  -> const_PackedLinkVector_span
+{
+  auto beg = reinterpret_cast<const VElt_t*>
+    (container.getDataArray (m_auxid));
+  return const_PackedLinkVector_span (beg, container.size_v());
+}
+
+
+/**
+ * @brief Get a span over the array of @c DataLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDataLinkSpan (const AuxVectorData& container) const
+  -> const_DataLink_span
+{
+  const AuxDataSpanBase* sp = container.getDataSpan (m_linkedAuxid);
+  return const_DataLink_span (reinterpret_cast<const DLink_t*>(sp->beg),
+                              sp->size);
+}
+
+
+/**
+ * @brief Get a span over spans of @c ElementLinks.
+ * @param container The container from which to fetch the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDataSpan (const AuxVectorData& container) const
+  -> const_span
+{
+  const_PackedLinkVector_span pvspan = getPackedLinkVectorSpan(container);
+  return const_span (pvspan,
+                     ConstVectorTransform_t (*container.getDataSpan (m_linkedAuxid)));
+}
+
+
+/**
+ * @brief Get a span over the vector of @c PackedLinks for a given element,
+ *        as a decoration.
+ * @param e The element for which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <IsConstAuxElement ELT>
+inline
+auto
+DECORATOR::getPackedLinkDecorSpan (const ELT& e) const
+  -> PackedLink_span
+{
+  auto elt = reinterpret_cast<VElt_t*>
+    (e.container()->getDecorationArray (this->m_auxid)) + e.index();
+  return PackedLink_span (elt->data(), elt->size());
+}
+
+
+/**
+ * @brief Get a span over the vector of @c PackedLinks for a given element,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ * @param index The index of the desired element.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkDecorSpan (const AuxVectorData& container, size_t index) const
+  -> PackedLink_span
+{
+  auto elt = reinterpret_cast<VElt_t*>
+    (container.getDecorationArray (this->m_auxid)) + index;
+  return PackedLink_span (elt->data(), elt->size());
+}
+
+
+/**
+ * @brief Get a span over the vectors of @c PackedLinks,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getPackedLinkVectorDecorSpan (const AuxVectorData& container) const
+  -> PackedLinkVector_span
+{
+  auto beg = reinterpret_cast<VElt_t*>
+    (container.getDecorationArray (m_auxid));
+  return PackedLinkVector_span (beg, container.size_v());
+}
+
+
+/**
+ * @brief Get a span over the array of @c DataLinks, as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDataLinkDecorSpan (const AuxVectorData& container) const
+  -> DataLink_span
+{
+  (void)container.getDecorationArray (this->m_linkedAuxid); // check for locking
+  const AuxDataSpanBase* sp = container.getDataSpan (m_linkedAuxid);
+  return DataLink_span (reinterpret_cast<DLink_t*>(sp->beg), sp->size);
+}
+
+
+/**
+ * @brief Get a span over spans of @c ElementLink proxies,
+ *        as a decoration.
+ * @param container The container from which to fetch the variable.
+ *
+ * The individual proxies may be converted to or assigned from @c ElementLink.
+ * Each element may also be assigned from a range of @c ElementLink,
+ * or converted to a vector of @c ElementLink.
+ *
+ * If the container is locked, this will allow fetching only variables
+ * that do not yet exist (in which case they will be marked as decorations)
+ * or variables already marked as decorations.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+inline
+auto
+DECORATOR::getDecorationSpan (const AuxVectorData& container) const
+  -> span
+{
+  PackedLinkVector_span pvspan = getPackedLinkVectorDecorSpan(container);
+  AuxVectorData& container_nc ATLAS_THREAD_SAFE = const_cast<AuxVectorData&> (container);
+  return span (pvspan,
+               ELSpanConverter (container_nc,
+                                this->m_auxid,
+                                this->m_linkedAuxid));
+}
+
+
+/**
+ * @brief Test to see if this variable exists in the store and is writable.
+ * @param e An element of the container which to test the variable.
+ */
+template <class CONT, class ALLOC, class VALLOC>
+template <IsConstAuxElement ELT>
+inline
+bool
+DECORATOR::isAvailableWritable (const ELT& e) const
+{
+  return e.container() &&
+    e.container()->isAvailableWritableAsDecoration (m_auxid) &&
+    e.container()->isAvailableWritableAsDecoration (m_linkedAuxid);
+}
+
+
+#undef DECORATOR
+
+
+} // namespace SG
diff --git a/Control/AthContainers/CMakeLists.txt b/Control/AthContainers/CMakeLists.txt
index b0a2e1245e317dd0e62faac9a2d73f59bfb67f5d..c7954b51003aae37e60d3a7b73fab58dce0de7ef 100644
--- a/Control/AthContainers/CMakeLists.txt
+++ b/Control/AthContainers/CMakeLists.txt
@@ -119,3 +119,4 @@ _add_test( PackedLinkVectorFactory_test )
 _add_test( ELProxy_test )
 _add_test( PackedLinkConstAccessor_test )
 _add_test( PackedLinkAccessor_test )
+_add_test( PackedLinkDecorator_test )
diff --git a/Control/AthContainers/share/PackedLinkDecorator_test.ref b/Control/AthContainers/share/PackedLinkDecorator_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..407792c4c5a29e48ea0c4cb9cf06f7f9a13735da
--- /dev/null
+++ b/Control/AthContainers/share/PackedLinkDecorator_test.ref
@@ -0,0 +1,5 @@
+AthContainers/PackedLinkDecorator_test
+test1
+test2
+test3
+test4
diff --git a/Control/AthContainers/test/PackedLinkDecorator_test.cxx b/Control/AthContainers/test/PackedLinkDecorator_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..3987d2cdf0891c8efff712673dfcf4cf16c8ddcc
--- /dev/null
+++ b/Control/AthContainers/test/PackedLinkDecorator_test.cxx
@@ -0,0 +1,754 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file AthContainers/test/PackedLinkDecorator_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Oct, 2023
+ * @brief Regression tests for PackedLinkDecorator
+ */
+
+#undef NDEBUG
+#include "AthContainers/PackedLinkDecorator.h"
+#include "AthContainers/AuxElement.h"
+#include "AthContainers/AuxStoreInternal.h"
+#include "AthContainers/exceptions.h"
+#include "TestTools/expect_exception.h"
+#include <iostream>
+#include <cassert>
+
+
+#ifdef XAOD_STANDALONE
+
+// Declared in DataLink.h but not defined.
+template <typename STORABLE>
+bool operator== (const DataLink<STORABLE>& a,
+                 const DataLink<STORABLE>& b)
+{
+  return a.key() == b.key() && a.source() == b.source();
+}
+
+#else
+
+#include "AthenaKernel/CLASS_DEF.h"
+CLASS_DEF( std::vector<int>, 12345, 0 )
+CLASS_DEF( std::vector<float>, 12346, 0 )
+#endif
+
+
+namespace SG {
+
+
+class AuxVectorBase
+  : public SG::AuxVectorData
+{
+public:
+  AuxVectorBase (size_t sz = 10) : m_sz (sz) {}
+  virtual size_t size_v() const { return m_sz; }
+  virtual size_t capacity_v() const { return m_sz; }
+
+  using SG::AuxVectorData::setStore;
+  void set (SG::AuxElement& b, size_t index)
+  {
+    b.setIndex (index, this);
+  }
+  void set (SG::ConstAuxElement& b, size_t index)
+  {
+    b.setIndex (index, this);
+  }
+  void clear (SG::AuxElement& b)
+  {
+    b.setIndex (0, 0);
+  }
+
+  static
+  void clearAux (SG::AuxElement& b)
+  {
+    b.clearAux();
+  }
+
+  static
+  void copyAux (SG::AuxElement& a, const SG::AuxElement& b)
+  {
+    a.copyAux (b);
+  }
+
+  static
+  void testAuxElementCtor (SG::AuxVectorData* container,
+                           size_t index)
+  {
+    SG::AuxElement bx (container, index);
+    assert (bx.index() == index);
+    assert (bx.container() == container);
+  }
+
+private:
+  size_t m_sz;
+};
+
+
+
+} // namespace SG
+
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  using Cont = std::vector<int>;
+  using PLink = SG::PackedLink<Cont>;
+  using DLink = DataLink<Cont>;
+
+  SG::Decorator<PLink> ptyp1 ("plink");
+
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  SG::auxid_t plink_id = r.findAuxID ("plink");
+  SG::auxid_t dlink_id = r.findAuxID ("plink_linked");
+
+  assert (ptyp1.auxid() == plink_id);
+  assert (ptyp1.linkedAuxid() == dlink_id);
+
+  {
+    SG::Decorator<PLink> p2 (plink_id);
+    assert (p2.auxid() == plink_id);
+    EXPECT_EXCEPTION (SG::ExcAuxTypeMismatch, (SG::Decorator<SG::PackedLink<std::vector<float> > > (plink_id)));
+
+    SG::auxid_t flink_id = r.getAuxID<SG::PackedLink<std::vector<float> > > ("flink");
+    EXPECT_EXCEPTION (SG::ExcNoLinkedVar, (SG::Decorator<SG::PackedLink<std::vector<float> > > (flink_id)));
+  }
+
+  SG::AuxElement b5;
+  SG::ConstAuxElement bc5;
+
+  assert (!ptyp1.isAvailable(b5));
+  assert (!ptyp1.isAvailable(bc5));
+  assert (!ptyp1.isAvailableWritable(b5));
+  assert (!ptyp1.isAvailableWritable(bc5));
+
+  SG::AuxVectorBase v;
+  const SG::AuxVectorBase& vc = v;
+  v.set (b5, 5);
+  v.set (bc5, 5);
+  SG::AuxStoreInternal store;
+  v.setStore (&store);
+
+  PLink* plink = reinterpret_cast<PLink*> (store.getData(plink_id, 10, 10));
+  DLink* dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  SG::IAuxTypeVector* linkedVec = store.linkedVector (plink_id);
+  assert (linkedVec->size() == 2);
+  plink[5] = PLink (1, 10);
+  dlink[1] = DLink (123);
+
+  assert (ptyp1.isAvailable(b5));
+  assert (ptyp1.isAvailable(bc5));
+  assert (ptyp1.isAvailableWritable(b5));
+  assert (ptyp1.isAvailableWritable(bc5));
+
+  SG::AuxElement b4;
+  SG::ConstAuxElement bc4;
+  v.set (b4, 4);
+  v.set (bc4, 4);
+  ptyp1.set (b4, ElementLink<Cont> (124, 11));
+  assert (linkedVec->size() == 3);
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  assert (plink[4] == PLink (2, 11));
+  assert (dlink[2] == DLink (124));
+
+  ptyp1.set (bc4, ElementLink<Cont> (124, 12));
+  assert (linkedVec->size() == 3);
+  assert (plink[4] == PLink (2, 12));
+  assert (dlink[2] == DLink (124));
+
+  assert (ptyp1 (b5).key() == 123);
+  assert (ptyp1 (b5).index() == 10);
+  assert (ptyp1 (bc5).key() == 123);
+  assert (ptyp1 (bc5).index() == 10);
+
+  {
+    assert (ptyp1 (bc5).key() == 123);
+    assert (ptyp1 (b5).key() == 123);
+
+    ptyp1 (bc5) = ElementLink<Cont> (124, 15);
+    assert (ptyp1 (bc5).key() == 124);
+    assert (ptyp1 (bc5).index() == 15);
+  }
+
+  {
+    ElementLink<Cont> el4 = ptyp1 (b4);
+    assert (el4.key() == 124);
+    assert (el4.index() == 12);
+  }
+  {
+    ElementLink<Cont> el4 = ptyp1 (bc4);
+    assert (el4.key() == 124);
+    assert (el4.index() == 12);
+  }
+
+  ptyp1 (b4) = ElementLink<Cont> (125, 12);
+  assert (linkedVec->size() == 4);
+  assert (plink[4] == PLink (3, 12));
+  assert (dlink[3] == DLink (125));
+
+  ptyp1 (bc4) = ElementLink<Cont> (125, 13);
+  assert (linkedVec->size() == 4);
+  assert (plink[4] == PLink (3, 13));
+  assert (dlink[3] == DLink (125));
+
+  ptyp1.set (v, 4, ElementLink<Cont> (123, 14));
+  assert (linkedVec->size() == 4);
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  assert (plink[4] == PLink (1, 14));
+  assert (ptyp1 (v, 4).key() == 123);
+  assert (ptyp1 (v, 4).index() == 14);
+
+  ptyp1 (v, 4) = ElementLink<Cont> (125, 15);
+  assert (plink[4] == PLink (3, 15));
+
+  assert (ptyp1.getPackedLinkArray (v) == plink);
+  assert (ptyp1.getDataLinkArray (v) == dlink);
+  assert (ptyp1.getPackedLinkArray (vc) == plink);
+  assert (ptyp1.getDataLinkArray (vc) == dlink);
+
+  v.lock();
+  assert (ptyp1.isAvailable(b5));
+  assert (ptyp1.isAvailable(bc5));
+  assert (!ptyp1.isAvailableWritable(b5));
+  assert (!ptyp1.isAvailableWritable(bc5));
+
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, ptyp1(b5) = ElementLink<Cont> (123, 21));
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, ptyp1(bc5) = ElementLink<Cont> (123, 22));
+
+  SG::Decorator<PLink> ptyp2 ("plink2");
+
+  assert (!ptyp2.isAvailable(b5));
+  assert (!ptyp2.isAvailable(bc5));
+  assert (!ptyp2.isAvailableWritable(b5));
+  assert (!ptyp2.isAvailableWritable(bc5));
+
+  ptyp2(bc5) = ElementLink<Cont> (123, 23);
+
+  assert (ptyp2.isAvailable(b5));
+  assert (ptyp2.isAvailable(bc5));
+  assert (ptyp2.isAvailableWritable(b5));
+  assert (ptyp2.isAvailableWritable(bc5));
+
+  assert (ptyp2 (b5).key() == 123);
+  assert (ptyp2 (b5).index() == 23);
+  assert (ptyp2 (bc5).key() == 123);
+  assert (ptyp2 (bc5).index() == 23);
+
+  ptyp2.set (bc5, ElementLink<Cont> (124, 24));
+  assert (ptyp2(bc5) == ElementLink<Cont> (124, 24));
+
+  assert (ptyp2.getPackedLinkArray (v)[5] == PLink (2, 24));
+  assert (ptyp2.getDataLinkArray (v)[2].key() == 124);
+
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, ptyp1.getPackedLinkDecorArray(v));
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, ptyp1.getDataLinkDecorArray(v));
+  assert (ptyp2.getPackedLinkDecorArray (v)[5] == PLink (2, 24));
+  assert (ptyp2.getDataLinkDecorArray (v)[2].key() == 124);
+}
+
+
+// spans
+void test2()
+{
+  std::cout << "test2\n";
+
+  using Cont = std::vector<int>;
+  using PLink = SG::PackedLink<Cont>;
+  using DLink = DataLink<Cont>;
+
+  SG::Decorator<PLink> ptyp1 ("plink");
+
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  SG::auxid_t plink_id = r.findAuxID ("plink");
+  SG::auxid_t dlink_id = r.findAuxID ("plink_linked");
+
+  SG::AuxVectorBase v (5);
+  const SG::AuxVectorBase& vc = v;
+  SG::AuxStoreInternal store;
+  v.setStore (&store);
+  PLink* plink = reinterpret_cast<PLink*> (store.getData(plink_id, 5, 5));
+  DLink* dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 3, 3));
+  plink[0] = PLink (1, 10);
+  plink[1] = PLink (2, 11);
+  plink[2] = PLink (0, 0);
+  plink[3] = PLink (1, 13);
+  plink[4] = PLink (2, 14);
+  dlink[1] = DLink (123);
+  dlink[2] = DLink (124);
+
+  auto pspanc = ptyp1.getPackedLinkSpan (vc);
+  auto dspanc = ptyp1.getDataLinkSpan (vc);
+  assert (pspanc.size() == 5);
+  assert (pspanc[1] == PLink (2, 11));
+  assert (pspanc[3] == PLink (1, 13));
+  assert (dspanc.size() == 3);
+  assert (dspanc[1].key() == 123);
+  assert (dspanc[2].key() == 124);
+
+  auto pspan = ptyp1.getPackedLinkDecorSpan (vc);
+  auto dspan = ptyp1.getDataLinkDecorSpan (vc);
+  assert (pspan.size() == 5);
+  assert (pspan[1] == PLink (2, 11));
+  assert (pspan[3] == PLink (1, 13));
+  assert (dspan.size() == 3);
+  assert (dspan[1].key() == 123);
+  assert (dspan[2].key() == 124);
+
+  auto spanc = ptyp1.getDataSpan (vc);
+  assert (spanc.size() == 5);
+  assert (!spanc.empty());
+  assert (spanc[1].key() == 124);
+  assert (spanc[1].index() == 11);
+  assert (spanc.front().key() == 123);
+  assert (spanc.front().index() == 10);
+  assert (spanc.back().key() == 124);
+  assert (spanc.back().index() == 14);
+
+  auto span = ptyp1.getDecorationSpan (v);
+  const auto& cspan = span;
+  assert (span.size() == 5);
+  assert (!span.empty());
+  assert (span[1].key() == 124);
+  assert (span[1].index() == 11);
+  assert (cspan[1].key() == 124);
+  assert (cspan[1].index() == 11);
+  assert (span.front().key() == 123);
+  assert (span.front().index() == 10);
+  assert (cspan.front().key() == 123);
+  assert (cspan.front().index() == 10);
+  assert (span.back().key() == 124);
+  assert (span.back().index() == 14);
+  assert (cspan.back().key() == 124);
+  assert (cspan.back().index() == 14);
+
+  std::vector<unsigned> idx;
+  spanc = ptyp1.getDataSpan (vc);
+  for (ElementLink<Cont> el : spanc) {
+    idx.push_back (el.isDefault() ? 0 : el.index());
+  }
+  assert (idx == (std::vector<unsigned> {10, 11, 0, 13, 14}));
+
+  idx.clear();
+  for (ElementLink<Cont> el : span) {
+    idx.push_back (el.isDefault() ? 0 : el.index());
+  }
+  assert (idx == (std::vector<unsigned> {10, 11, 0, 13, 14}));
+
+  idx.clear();
+  for (ElementLink<Cont> el : cspan) {
+    idx.push_back (el.isDefault() ? 0 : el.index());
+  }
+  assert (idx == (std::vector<unsigned> {10, 11, 0, 13, 14}));
+
+  span[1] = ElementLink<Cont> (125, 21);
+  assert (span[1].key() == 125);
+  assert (span[1].index() == 21);
+  assert (pspan[1] == PLink (3, 21));
+  dspan = ptyp1.getDataLinkDecorSpan (v);
+  assert (dspan.size() == 4);
+  assert (dspan[3].key() == 125);
+
+  span.front() = ElementLink<Cont>();
+  assert (span[0].isDefault());
+  assert (pspan[0] == PLink (0, 0));
+
+  span.back() = ElementLink<Cont> (123, 22);
+  assert (span[4].key() == 123);
+  assert (span[4].index() == 22);
+  assert (pspan[4] == PLink (1, 22));
+
+  auto beg = span.begin();
+  auto end = span.end();
+  for (; beg != end; ++beg) {
+    ElementLink<Cont> el = *beg;
+    if (!el.isDefault()) {
+      el.resetWithKeyAndIndex (el.key(), el.index()+1);
+    }
+    *beg = el;
+  }
+
+  idx.clear();
+  for (ElementLink<Cont> el : cspan) {
+    idx.push_back (el.isDefault() ? 0 : el.index());
+  }
+  assert (idx == (std::vector<unsigned> {0, 22, 0, 14, 23}));
+
+  idx.clear();
+  spanc = ptyp1.getDataSpan (vc);
+  for (ElementLink<Cont> el : spanc) {
+    idx.push_back (el.isDefault() ? 0 : el.index());
+  }
+  assert (idx == (std::vector<unsigned> {0, 22, 0, 14, 23}));
+
+  v.lock();
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, ptyp1.getDecorationSpan(v));
+
+  SG::Decorator<PLink> ptyp2 ("plink2");
+  ptyp2.set (vc, 3, ElementLink<Cont> (124, 24));
+  {
+    auto span2 = ptyp2.getDecorationSpan (vc);
+    assert (span2.size() == 5);
+    assert (span2[3] == ElementLink<Cont> (124, 24));
+    span2[3] = ElementLink<Cont> (124, 25);
+  }
+
+  {
+    auto span1 = ptyp1.getDataSpan (vc);
+    auto span2 = ptyp2.getDataSpan (vc);
+    assert (span1.size() == 5);
+    assert (span2.size() == 5);
+    assert (span1[1] == ElementLink<Cont> (125, 22));
+    assert (span2[3] == ElementLink<Cont> (124, 25));
+  }
+}
+
+
+// vector<PackedLink>
+void test3()
+{
+  std::cout << "test3\n";
+
+  using Cont = std::vector<int>;
+  using PLink = SG::PackedLink<Cont>;
+  using DLink = DataLink<Cont>;
+  using VElt = std::vector<PLink>;
+
+  SG::Decorator<VElt> vtyp1 ("vlink");
+
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  SG::auxid_t vlink_id = r.findAuxID ("vlink");
+  SG::auxid_t dlink_id = r.findAuxID ("vlink_linked");
+
+  assert (vtyp1.auxid() == vlink_id);
+  assert (vtyp1.linkedAuxid() == dlink_id);
+
+  {
+    SG::Decorator<VElt> v2 (vlink_id);
+    assert (v2.auxid() == vlink_id);
+    EXPECT_EXCEPTION (SG::ExcAuxTypeMismatch, (SG::Decorator<std::vector<SG::PackedLink<std::vector<float> > > > (vlink_id)));
+
+    SG::auxid_t fvlink_id = r.getAuxID<std::vector<SG::PackedLink<std::vector<float> > > > ("fvlink");
+    EXPECT_EXCEPTION (SG::ExcNoLinkedVar, (SG::Decorator<std::vector<SG::PackedLink<std::vector<float> > > > (fvlink_id)));
+  }
+
+  SG::AuxElement b5;
+  SG::ConstAuxElement bc5;
+
+  assert (!vtyp1.isAvailable(b5));
+  assert (!vtyp1.isAvailable(bc5));
+  assert (!vtyp1.isAvailableWritable(b5));
+  assert (!vtyp1.isAvailableWritable(bc5));
+
+  SG::AuxVectorBase v;
+  const SG::AuxVectorBase& vc = v;
+  v.set (b5, 5);
+  v.set (bc5, 5);
+  SG::AuxStoreInternal store;
+  v.setStore (&store);
+
+  VElt* vlink = reinterpret_cast<VElt*> (store.getData(vlink_id, 10, 10));
+  DLink* dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  SG::IAuxTypeVector* linkedVec = store.linkedVector (vlink_id);
+  assert (linkedVec->size() == 2);
+  vlink[5] = VElt{{1, 10}, {0, 0}, {1, 11}};
+  dlink[1] = DLink (123);
+
+  assert (vtyp1.isAvailable(b5));
+  assert (vtyp1.isAvailable(bc5));
+  assert (vtyp1.isAvailableWritable(b5));
+  assert (vtyp1.isAvailableWritable(bc5));
+
+  SG::AuxElement b4;
+  SG::ConstAuxElement bc4;
+  v.set (b4, 4);
+  v.set (bc4, 4);
+  vtyp1.set (b4, std::vector<ElementLink<Cont> > {{124, 12}, {123, 13}, {0, 0}});
+  assert (linkedVec->size() == 3);
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  assert (vlink[4] == (VElt{{2, 12}, {1, 13}, {0, 0}}));
+  assert (dlink[2] == DLink (124));
+
+  vtyp1.set (bc4, std::vector<ElementLink<Cont> > {{124, 14}, {123, 15}, {0, 0}});
+  assert (linkedVec->size() == 3);
+  assert (vlink[4] == (VElt{{2, 14}, {1, 15}, {0, 0}}));
+  assert (dlink[2] == DLink (124));
+
+  assert (vtyp1 (b5).size() == 3);
+  assert (vtyp1 (bc5).size() == 3);
+  assert (vtyp1 (b5)[0].key() == 123);
+  assert (vtyp1 (b5)[0].index() == 10);
+  assert (vtyp1 (b5)[1].key() == 0);
+  assert (vtyp1 (bc5)[2].key() == 123);
+  assert (vtyp1 (bc5)[2].index() == 11);
+
+  {
+    std::vector<int> v;
+    for (const ElementLink<Cont> el : vtyp1(b5)) {
+      if (el.isDefault()) {
+        v.push_back (0);
+      }
+      else {
+        v.push_back (el.key());
+        v.push_back (el.index());
+      }
+    }
+    assert (v == (std::vector<int> {123, 10, 0, 123, 11}));
+  }
+
+  {
+    std::vector<int> v;
+    for (const ElementLink<Cont> el : vtyp1(bc5)) {
+      if (el.isDefault()) {
+        v.push_back (0);
+      }
+      else {
+        v.push_back (el.key());
+        v.push_back (el.index());
+      }
+    }
+    assert (v == (std::vector<int> {123, 10, 0, 123, 11}));
+  }
+
+  {
+    assert (vtyp1 (bc5).size() == 3);
+    assert (vtyp1 (bc5)[2].key() == 123);
+
+    vtyp1 (bc5) = std::vector<ElementLink<Cont> > {{124, 15}, {123, 16}};
+    assert (vtyp1 (b5).size() == 2);
+    assert (vtyp1 (b5)[0].key() == 124);
+    assert (vtyp1 (b5)[0].index() == 15);
+    assert (vtyp1 (b5)[1].key() == 123);
+    assert (vtyp1 (b5)[1].index() == 16);
+  }
+
+  {
+    std::vector<ElementLink<Cont> > el4 = vtyp1 (b4);
+    assert (el4 == (std::vector<ElementLink<Cont> > {{124, 14}, {123, 15}, {}}));
+  }
+  {
+    std::vector<ElementLink<Cont> > el4 = vtyp1 (bc4);
+    assert (el4 == (std::vector<ElementLink<Cont> > {{124, 14}, {123, 15}, {}}));
+  }
+
+  vtyp1 (b4)[1] = ElementLink<Cont> (125, 17);
+  assert (vlink[4][1] == PLink (3, 17));
+  assert (linkedVec->size() == 4);
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 2, 2));
+  assert (dlink[3] == DLink (125));
+
+  vtyp1 (bc4)[1] = ElementLink<Cont> (125, 18);
+  assert (vlink[4][1] == PLink (3, 18));
+  assert (linkedVec->size() == 4);
+  assert (dlink[3] == DLink (125));
+
+  vtyp1 (b4) = std::vector<ElementLink<Cont> > {{123, 21}};
+  assert (linkedVec->size() == 4);
+  assert (vlink[4] == (VElt{{1, 21}}));
+
+  vtyp1 (bc4) = std::vector<ElementLink<Cont> > {{123, 22}};
+  assert (linkedVec->size() == 4);
+  assert (vlink[4] == (VElt{{1, 22}}));
+
+  vtyp1.set (v, 4, std::vector<ElementLink<Cont> > {{123, 14}});
+  assert (linkedVec->size() == 4);
+  assert (vlink[4] == (VElt{{1, 14}}));
+  assert (vtyp1 (v, 4)[0].key() == 123);
+  assert (vtyp1 (v, 4)[0].index() == 14);
+
+  vtyp1 (v, 4) = std::vector<ElementLink<Cont> > {{123, 15}};
+  assert (linkedVec->size() == 4);
+  assert (vlink[4] == (VElt{{1, 15}}));
+  assert (vtyp1 (v, 4)[0].key() == 123);
+  assert (vtyp1 (v, 4)[0].index() == 15);
+
+  assert (vtyp1.getPackedLinkVectorArray (v) == vlink);
+  assert (vtyp1.getDataLinkArray (v) == dlink);
+  assert (vtyp1.getPackedLinkVectorArray (vc) == vlink);
+  assert (vtyp1.getDataLinkArray (vc) == dlink);
+
+  vtyp1 (bc4).push_back (ElementLink<Cont> {123, 31});
+  assert (vlink[4] == (VElt{{1, 15}, {1, 31}}));
+
+  v.lock();
+  assert (vtyp1.isAvailable(b5));
+  assert (vtyp1.isAvailable(bc5));
+  assert (!vtyp1.isAvailableWritable(b5));
+  assert (!vtyp1.isAvailableWritable(bc5));
+
+  // Empty vectors.
+  {
+    SG::AuxVectorBase v2;
+    SG::AuxStoreInternal store2;
+    v2.setStore (&store2);
+    (void)store2.getData(vlink_id, 10, 10);
+    (void)store2.getData(dlink_id, 0, 0);
+    assert (vtyp1 (v2, 5).empty());
+  }
+
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1(b5)[0] = ElementLink<Cont> (123, 21));
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1(bc5)[0] = ElementLink<Cont> (123, 22));
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1(bc4).push_back (ElementLink<Cont> {123, 32}));
+
+  SG::Decorator<VElt> vtyp2 ("vlink2");
+
+  assert (!vtyp2.isAvailable(b5));
+  assert (!vtyp2.isAvailable(bc5));
+  assert (!vtyp2.isAvailableWritable(b5));
+  assert (!vtyp2.isAvailableWritable(bc5));
+
+  vtyp2(bc5) = std::vector<ElementLink<Cont> > {{123, 23}};
+
+  assert (vtyp2.isAvailable(b5));
+  assert (vtyp2.isAvailable(bc5));
+  assert (vtyp2.isAvailableWritable(b5));
+  assert (vtyp2.isAvailableWritable(bc5));
+
+  assert (vtyp2 (b5).size() == 1);
+  assert (vtyp2 (bc5).size() == 1);
+  assert (vtyp2 (b5)[0].key() == 123);
+  assert (vtyp2 (b5)[0].index() == 23);
+  assert (vtyp2 (bc5)[0].key() == 123);
+  assert (vtyp2 (bc5)[0].index() == 23);
+
+  vtyp2.set (bc5, std::vector<ElementLink<Cont> > {{124, 24}});
+  assert (vtyp2(bc5)[0] == ElementLink<Cont> (124, 24));
+
+  assert (vtyp2.getPackedLinkVectorArray (v)[5][0] == PLink (2, 24));
+  assert (vtyp2.getDataLinkArray (v)[2].key() == 124);
+
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1.getPackedLinkVectorDecorArray(v));
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1.getDataLinkDecorArray(v));
+  assert (vtyp2.getPackedLinkVectorDecorArray (v)[5][0] == PLink (2, 24));
+  assert (vtyp2.getDataLinkDecorArray (v)[2].key() == 124);
+}
+
+
+// spans with vectors
+void test4()
+{
+  std::cout << "test4\n";
+
+  using Cont = std::vector<int>;
+  using PLink = SG::PackedLink<Cont>;
+  using DLink = DataLink<Cont>;
+  using VElt = std::vector<PLink>;
+
+  SG::Decorator<VElt> vtyp1 ("vlink");
+
+  SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
+  SG::auxid_t vlink_id = r.findAuxID ("vlink");
+  SG::auxid_t dlink_id = r.findAuxID ("vlink_linked");
+
+  SG::AuxVectorBase v (5);
+  const SG::AuxVectorBase& vc = v;
+  SG::AuxStoreInternal store;
+  v.setStore (&store);
+  VElt* vlink = reinterpret_cast<VElt*> (store.getData(vlink_id, 5, 5));
+  DLink* dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 3, 3));
+  vlink[0] = VElt{{1, 10}, {0, 0}, {1, 11}};
+  vlink[1] = VElt{{2, 12}};
+  vlink[3] = VElt{{0, 0}};
+  vlink[4] = VElt{{1, 13}, {2, 14}};
+  dlink[1] = DLink (123);
+  dlink[2] = DLink (124);
+
+  {
+    auto dspan = vtyp1.getDataLinkSpan (v);
+    assert (dspan.size() == 3);
+    assert (dspan[1].key() == 123);
+    assert (dspan[2].key() == 124);
+  }
+
+  {
+    auto pvspan = vtyp1.getPackedLinkVectorSpan (vc);
+    assert (pvspan.size() == 5);
+    assert (pvspan[4] == (VElt{{1, 13}, {2, 14}}));
+  }
+
+  {
+    auto pspanc = vtyp1.getPackedLinkSpan (vc, 1);
+    assert (pspanc.size() == 1);
+    assert (pspanc[0] == PLink (2, 12));
+  }
+
+  {
+    auto dspan = vtyp1.getDataLinkDecorSpan (vc);
+    assert (dspan.size() == 3);
+    assert (dspan[1].key() == 123);
+    assert (dspan[2].key() == 124);
+  }
+
+  {
+    auto pspan = vtyp1.getPackedLinkDecorSpan (vc, 1);
+    assert (pspan.size() == 1);
+    assert (pspan[0] == PLink (2, 12));
+  }
+
+  {
+    auto pvspan = vtyp1.getPackedLinkVectorDecorSpan (vc);
+    assert (pvspan.size() == 5);
+    assert (pvspan[4] == (VElt{{1, 13}, {2, 14}}));
+  }
+
+  auto spanc = vtyp1.getDataSpan (vc);
+  assert (spanc.size() == 5);
+  assert (!spanc.empty());
+  assert (spanc[0].size() == 3);
+  assert (spanc[0][2].key() == 123);
+  assert (spanc[0][2].index() == 11);
+  assert (spanc.back().front().key() == 123);
+  assert (spanc.back().front().index() == 13);
+
+  auto span = vtyp1.getDecorationSpan (v);
+  assert (span.size() == 5);
+  assert (span[0].size() == 3);
+  assert (span[0][2].key() == 123);
+  assert (span[0][2].index() == 11);
+  assert (span.back().front().key() == 123);
+  assert (span.back().front().index() == 13);
+  assert (span.front().front().key() == 123);
+  assert (span.front().front().index() == 10);
+
+  std::vector<unsigned> idx;
+  for (auto s : span) {
+    for (ElementLink<Cont> el : s) {
+      idx.push_back (el.isDefault() ? 0 : el.index());
+    }
+  }
+  assert (idx == (std::vector<unsigned> {10, 0, 11, 12, 0, 13, 14}));
+
+  span[0][1] = ElementLink<Cont> (125, 21);
+
+  SG::IAuxTypeVector* linkedVec = store.linkedVector (vlink_id);
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 3, 3));
+  assert (linkedVec->size() == 4);
+  assert (dlink[3] == DLink (125));
+  assert (vlink[0] == (VElt{{1, 10}, {3, 21}, {1, 11}}));
+
+  span[2] = std::vector<ElementLink<Cont> > {{124, 22}, {}, {126, 23}};
+
+  dlink = reinterpret_cast<DLink*> (store.getData(dlink_id, 3, 3));
+  assert (linkedVec->size() == 5);
+  assert (dlink[4] == DLink (126));
+  assert (vlink[2] == (VElt{{2, 22}, {0, 0}, {4, 23}}));
+
+  std::vector<ElementLink<Cont> > elv = span[4];
+  assert (elv == (std::vector<ElementLink<Cont> > {{123, 13}, {124, 14}}));
+
+  v.lock();
+  EXPECT_EXCEPTION (SG::ExcStoreLocked, vtyp1.getDecorationSpan(v));
+}
+
+
+int main()
+{
+  std::cout << "AthContainers/PackedLinkDecorator_test\n";
+  test1();
+  test2();
+  test3();
+  test4();
+  return 0;
+}