[arrays] Remove hb_supplier_t<>
diff --git a/src/hb-array.hh b/src/hb-array.hh
index c18d4dc..33837b0 100644
--- a/src/hb-array.hh
+++ b/src/hb-array.hh
@@ -269,16 +269,5 @@
 
 typedef hb_array_t<const char> hb_bytes_t;
 
-template <typename Type> struct hb_supplier_t : hb_array_t<const Type>
-{
-  HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (hb_supplier_t, Type);
-
-  hb_supplier_t (const Type *array, unsigned int len) : hb_array_t<const Type> (array, len) {}
-  hb_supplier_t (hb_array_t<const Type> v) : hb_array_t<const Type> (v) {}
-
-  /* Make sure no one calls the custom & operator on us. */
-  Type * operator & () const;
-};
-
 
 #endif /* HB_ARRAY_HH */
diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh
index 7756ca8..709bdef 100644
--- a/src/hb-cff2-interp-cs.hh
+++ b/src/hb-cff2-interp-cs.hh
@@ -52,7 +52,7 @@
   void set_real (double v) { reset_blends (); Number::set_real (v); }
 
   void set_blends (unsigned int numValues_, unsigned int valueIndex_,
-			  unsigned int numBlends, const hb_array_t<const BlendArg> &blends_)
+			  unsigned int numBlends, hb_array_t<const BlendArg> blends_)
   {
     numValues = numValues_;
     valueIndex = valueIndex_;
diff --git a/src/hb-face.cc b/src/hb-face.cc
index 825021f..8bb8c51 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -648,11 +648,7 @@
   bool is_cff = data->tables.lsearch (HB_TAG ('C','F','F',' ')) || data->tables.lsearch (HB_TAG ('C','F','F','2'));
   hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
 
-  hb_supplier_t<hb_face_builder_data_t::table_entry_t> supplier (data->tables);
-  bool ret = f->serialize_single (&c,
-				  sfnt_tag,
-				  supplier,
-				  table_count);
+  bool ret = f->serialize_single (&c, sfnt_tag, data->tables.as_array ());
 
   c.end_serialize ();
 
diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh
index 8890f52..822a92d 100644
--- a/src/hb-open-file.hh
+++ b/src/hb-open-file.hh
@@ -121,8 +121,7 @@
   template <typename item_t>
   bool serialize (hb_serialize_context_t *c,
 		  hb_tag_t sfnt_tag,
-		  hb_supplier_t<item_t> &items,
-		  unsigned int table_count)
+		  hb_array_t<item_t> items)
   {
     TRACE_SERIALIZE (this);
     /* Alloc 12 for the OTHeader. */
@@ -131,13 +130,13 @@
     sfnt_version.set (sfnt_tag);
     /* Take space for numTables, searchRange, entrySelector, RangeShift
      * and the TableRecords themselves.  */
-    if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
+    if (unlikely (!tables.serialize (c, items.len))) return_trace (false);
 
     const char *dir_end = (const char *) c->head;
     HBUINT32 *checksum_adjustment = nullptr;
 
     /* Write OffsetTables, alloc for and write actual table blobs. */
-    for (unsigned int i = 0; i < table_count; i++)
+    for (unsigned int i = 0; i < tables.len; i++)
     {
       TableRecord &rec = tables.arrayZ[i];
       hb_blob_t *blob = items[i].blob;
@@ -164,7 +163,6 @@
 
       rec.checkSum.set_for_data (start, end - start);
     }
-    items += table_count;
 
     tables.qsort ();
 
@@ -175,7 +173,7 @@
       /* The following line is a slower version of the following block. */
       //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
       checksum.set_for_data (this, dir_end - (const char *) this);
-      for (unsigned int i = 0; i < table_count; i++)
+      for (unsigned int i = 0; i < items.len; i++)
       {
 	TableRecord &rec = tables.arrayZ[i];
 	checksum.set (checksum + rec.checkSum);
@@ -485,13 +483,12 @@
   template <typename item_t>
   bool serialize_single (hb_serialize_context_t *c,
 			 hb_tag_t sfnt_tag,
-			 hb_supplier_t<item_t> &items,
-			 unsigned int table_count)
+			 hb_array_t<item_t> items)
   {
     TRACE_SERIALIZE (this);
     assert (sfnt_tag != TTCTag);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    return_trace (u.fontFace.serialize (c, sfnt_tag, items, table_count));
+    return_trace (u.fontFace.serialize (c, sfnt_tag, items));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 0dfcd3a..6517c6b 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -553,15 +553,12 @@
     if (unlikely (!c->extend (*this))) return_trace (false);
     return_trace (true);
   }
-  bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<Type> &items,
-		  unsigned int items_len)
+  bool serialize (hb_serialize_context_t *c, hb_array_t<const Type> items)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!serialize (c, items_len))) return_trace (false);
-    for (unsigned int i = 0; i < items_len; i++)
+    if (unlikely (!serialize (c, items.len))) return_trace (false);
+    for (unsigned int i = 0; i < items.len; i++)
       arrayZ[i] = items[i];
-    items += items_len;
     return_trace (true);
   }
 
@@ -701,17 +698,14 @@
   { return lenP1.static_size + (lenP1 ? lenP1 - 1 : 0) * Type::static_size; }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<Type> &items,
-		  unsigned int items_len)
+		  hb_array_t<const Type> items)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    lenP1.set (items_len); /* TODO(serialize) Overflow? */
-    if (unlikely (!items_len)) return_trace (true);
+    lenP1.set (items.len + 1); /* TODO(serialize) Overflow? */
     if (unlikely (!c->extend (*this))) return_trace (false);
-    for (unsigned int i = 0; i < items_len - 1; i++)
+    for (unsigned int i = 0; i < items.len; i++)
       arrayZ[i] = items[i];
-    items += items_len - 1;
     return_trace (true);
   }
 
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 2f8c641..7567e52 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -495,8 +495,7 @@
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    hb_supplier_t<CmapSubtableLongGroup> supplier (group_data);
-    if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
+    if (unlikely (!groups.serialize (c, group_data.as_array ()))) return_trace (false);
     return true;
   }
 
diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh
index ac73920..f11261a 100644
--- a/src/hb-ot-layout-common.hh
+++ b/src/hb-ot-layout-common.hh
@@ -827,17 +827,10 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    glyphArray.len.set (num_glyphs);
-    if (unlikely (!c->extend (glyphArray))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      glyphArray[i] = glyphs[i];
-    glyphs += num_glyphs;
-    return_trace (true);
+    return_trace (glyphArray.serialize (c, glyphs));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -902,20 +895,19 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!num_glyphs))
+    if (unlikely (!glyphs.len))
     {
       rangeRecord.len.set (0);
       return_trace (true);
     }
 
     unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
       if (glyphs[i - 1] + 1 != glyphs[i])
 	num_ranges++;
     rangeRecord.len.set (num_ranges);
@@ -924,7 +916,7 @@
     unsigned int range = 0;
     rangeRecord[range].start = glyphs[0];
     rangeRecord[range].value.set (0);
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
     {
       if (glyphs[i - 1] + 1 != glyphs[i])
       {
@@ -934,7 +926,6 @@
       }
       rangeRecord[range].end = glyphs[i];
     }
-    glyphs += num_glyphs;
     return_trace (true);
   }
 
@@ -1051,22 +1042,21 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
     unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
       if (glyphs[i - 1] + 1 != glyphs[i])
 	num_ranges++;
-    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
+    u.format.set (glyphs.len * 2 < num_ranges * 3 ? 1 : 2);
 
     switch (u.format)
     {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs));
+    case 2: return_trace (u.format2.serialize (c, glyphs));
     default:return_trace (false);
     }
   }
@@ -1189,9 +1179,8 @@
  */
 
 static inline void ClassDef_serialize (hb_serialize_context_t *c,
-				       hb_supplier_t<GlyphID> &glyphs,
-				       hb_supplier_t<HBUINT16> &klasses,
-				       unsigned int num_glyphs);
+				       hb_array_t<const GlyphID> glyphs,
+				       hb_array_t<const HBUINT16> klasses);
 
 struct ClassDefFormat1
 {
@@ -1204,14 +1193,13 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<HBUINT16> &glyphs,
-		  hb_supplier_t<HBUINT16> &klasses,
-		  unsigned int num_glyphs)
+		  hb_array_t<const HBUINT16> glyphs,
+		  hb_array_t<const HBUINT16> klasses)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!num_glyphs))
+    if (unlikely (!glyphs.len))
     {
       startGlyph.set (0);
       classValue.len.set (0);
@@ -1219,7 +1207,7 @@
     }
 
     hb_codepoint_t glyph_min = (hb_codepoint_t) -1, glyph_max = 0;
-    for (unsigned int i = 0; i < num_glyphs; i++)
+    for (unsigned int i = 0; i < glyphs.len; i++)
     {
       glyph_min = MIN<hb_codepoint_t> (glyph_min, glyphs[i]);
       glyph_max = MAX<hb_codepoint_t> (glyph_max, glyphs[i]);
@@ -1229,10 +1217,9 @@
     classValue.len.set (glyph_max - glyph_min + 1);
     if (unlikely (!c->extend (classValue))) return_trace (false);
 
-    for (unsigned int i = 0; i < num_glyphs; i++)
+    for (unsigned int i = 0; i < glyphs.len; i++)
       classValue[glyphs[i] - glyph_min] = klasses[i];
-    glyphs += num_glyphs;
-    klasses += num_glyphs;
+
     return_trace (true);
   }
 
@@ -1255,13 +1242,7 @@
       klasses.push()->set (value);
     }
     c->serializer->propagate_error (glyphs, klasses);
-
-    hb_supplier_t<GlyphID> glyphs_supplier (glyphs);
-    hb_supplier_t<HBUINT16> klasses_supplier (klasses);
-    ClassDef_serialize (c->serializer,
-			glyphs_supplier,
-			klasses_supplier,
-			glyphs.len);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
     return_trace (glyphs.len);
   }
 
@@ -1352,21 +1333,20 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<HBUINT16> &glyphs,
-		  hb_supplier_t<HBUINT16> &klasses,
-		  unsigned int num_glyphs)
+		  hb_array_t<const HBUINT16> glyphs,
+		  hb_array_t<const HBUINT16> klasses)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
-    if (unlikely (!num_glyphs))
+    if (unlikely (!glyphs.len))
     {
       rangeRecord.len.set (0);
       return_trace (true);
     }
 
     unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
       if (glyphs[i - 1] + 1 != glyphs[i] ||
 	  klasses[i - 1] != klasses[i])
 	num_ranges++;
@@ -1376,7 +1356,7 @@
     unsigned int range = 0;
     rangeRecord[range].start = glyphs[0];
     rangeRecord[range].value.set (klasses[0]);
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
     {
       if (glyphs[i - 1] + 1 != glyphs[i] ||
 	  klasses[i - 1] != klasses[i])
@@ -1387,7 +1367,6 @@
       }
       rangeRecord[range].end = glyphs[i];
     }
-    glyphs += num_glyphs;
     return_trace (true);
   }
 
@@ -1414,13 +1393,7 @@
       }
     }
     c->serializer->propagate_error (glyphs, klasses);
-
-    hb_supplier_t<GlyphID> glyphs_supplier (glyphs);
-    hb_supplier_t<HBUINT16> klasses_supplier (klasses);
-    ClassDef_serialize (c->serializer,
-			glyphs_supplier,
-			klasses_supplier,
-			glyphs.len);
+    ClassDef_serialize (c->serializer, glyphs, klasses);
     return_trace (glyphs.len);
   }
 
@@ -1509,21 +1482,20 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<HBUINT16> &klasses,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const HBUINT16> klasses)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
 
     hb_codepoint_t glyph_min = (hb_codepoint_t) -1, glyph_max = 0;
-    for (unsigned int i = 0; i < num_glyphs; i++)
+    for (unsigned int i = 0; i < glyphs.len; i++)
     {
       glyph_min = MIN<hb_codepoint_t> (glyph_min, glyphs[i]);
       glyph_max = MAX<hb_codepoint_t> (glyph_max, glyphs[i]);
     }
     unsigned int num_ranges = 1;
-    for (unsigned int i = 1; i < num_glyphs; i++)
+    for (unsigned int i = 1; i < glyphs.len; i++)
       if (glyphs[i - 1] + 1 != glyphs[i] ||
 	  klasses[i - 1] != klasses[i])
 	num_ranges++;
@@ -1531,8 +1503,8 @@
 
     switch (u.format)
     {
-    case 1: return_trace (u.format1.serialize (c, glyphs, klasses, num_glyphs));
-    case 2: return_trace (u.format2.serialize (c, glyphs, klasses, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs, klasses));
+    case 2: return_trace (u.format2.serialize (c, glyphs, klasses));
     default:return_trace (false);
     }
   }
@@ -1610,15 +1582,9 @@
 };
 
 static inline void ClassDef_serialize (hb_serialize_context_t *c,
-				       hb_supplier_t<GlyphID> &glyphs,
-				       hb_supplier_t<HBUINT16> &klasses,
-				       unsigned int num_glyphs)
-{
-  c->start_embed<ClassDef> ()->serialize (c,
-					  glyphs,
-					  klasses,
-					  num_glyphs);
-}
+				       hb_array_t<const GlyphID> glyphs,
+				       hb_array_t<const HBUINT16> klasses)
+{ c->start_embed<ClassDef> ()->serialize (c, glyphs, klasses); }
 
 
 /*
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index fb59921..180e7f2 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -36,9 +36,8 @@
 
 
 static inline void SingleSubst_serialize (hb_serialize_context_t *c,
-					  hb_supplier_t<GlyphID> &glyphs,
-					  hb_supplier_t<GlyphID> &substitutes,
-					  unsigned int num_glyphs);
+					  hb_array_t<const GlyphID> glyphs,
+					  hb_array_t<const GlyphID> substitutes);
 
 struct SingleSubstFormat1
 {
@@ -95,13 +94,12 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs,
+		  hb_array_t<const GlyphID> glyphs,
 		  int delta)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
     deltaGlyphID.set (delta); /* TODO(serialize) overflow? */
     return_trace (true);
   }
@@ -121,13 +119,7 @@
       to.push ()->set (glyph_map[(iter.get_glyph () + delta) & 0xFFFF]);
     }
     c->serializer->propagate_error (from, to);
-
-    hb_supplier_t<GlyphID> from_supplier (from);
-    hb_supplier_t<GlyphID> to_supplier (to);
-    SingleSubst_serialize (c->serializer,
-			   from_supplier,
-			   to_supplier,
-			   from.len);
+    SingleSubst_serialize (c->serializer, from, to);
     return_trace (from.len);
   }
 
@@ -201,14 +193,13 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<GlyphID> &substitutes,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, substitutes, num_glyphs))) return_trace (false);
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
+    if (unlikely (!substitute.serialize (c, substitutes))) return_trace (false);
+    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs))) return_trace (false);
     return_trace (true);
   }
 
@@ -226,13 +217,7 @@
       to.push ()->set (glyph_map[substitute[iter.get_coverage ()]]);
     }
     c->serializer->propagate_error (from, to);
-
-    hb_supplier_t<GlyphID> from_supplier (from);
-    hb_supplier_t<GlyphID> to_supplier (to);
-    SingleSubst_serialize (c->serializer,
-			   from_supplier,
-			   to_supplier,
-			   from.len);
+    SingleSubst_serialize (c->serializer, from, to);
     return_trace (from.len);
   }
 
@@ -257,19 +242,19 @@
 struct SingleSubst
 {
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<GlyphID> &substitutes,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 2;
     int delta = 0;
-    if (num_glyphs) {
+    if (glyphs.len)
+    {
       format = 1;
       /* TODO(serialize) check for wrap-around */
       delta = substitutes[0] - glyphs[0];
-      for (unsigned int i = 1; i < num_glyphs; i++)
+      for (unsigned int i = 1; i < glyphs.len; i++)
 	if (delta != (int) (substitutes[i] - glyphs[i])) {
 	  format = 2;
 	  break;
@@ -277,8 +262,8 @@
     }
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, num_glyphs, delta));
-    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes, num_glyphs));
+    case 1: return_trace (u.format1.serialize (c, glyphs, delta));
+    case 2: return_trace (u.format2.serialize (c, glyphs, substitutes));
     default:return_trace (false);
     }
   }
@@ -305,15 +290,9 @@
 
 static inline void
 SingleSubst_serialize (hb_serialize_context_t *c,
-		       hb_supplier_t<GlyphID> &glyphs,
-		       hb_supplier_t<GlyphID> &substitutes,
-		       unsigned int num_glyphs)
-{
-  c->start_embed<SingleSubst> ()->serialize (c,
-					     glyphs,
-					     substitutes,
-					     num_glyphs);
-}
+		       hb_array_t<const GlyphID> glyphs,
+		       hb_array_t<const GlyphID> substitutes)
+{ c->start_embed<SingleSubst> ()->serialize (c, glyphs, substitutes); }
 
 struct Sequence
 {
@@ -364,13 +343,10 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!substitute.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    return_trace (substitute.serialize (c, glyphs));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -432,21 +408,22 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<unsigned int> &substitute_len_list,
-		  unsigned int num_glyphs,
-		  hb_supplier_t<GlyphID> &substitute_glyphs_list)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const unsigned int> substitute_len_list,
+		  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!sequence.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!sequence[i].serialize (c, this).serialize (c,
-								substitute_glyphs_list,
-								substitute_len_list[i]))) return_trace (false);
-    substitute_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!sequence.serialize (c, glyphs.len))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.len; i++)
+    {
+      unsigned int substitute_len = substitute_len_list[i];
+      if (unlikely (!sequence[i].serialize (c, this)
+				.serialize (c, substitute_glyphs_list.sub_array (0, substitute_len))))
+	return_trace (false);
+      substitute_glyphs_list += substitute_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -477,17 +454,16 @@
 struct MultipleSubst
 {
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<unsigned int> &substitute_len_list,
-		  unsigned int num_glyphs,
-		  hb_supplier_t<GlyphID> &substitute_glyphs_list)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const unsigned int> substitute_len_list,
+		  hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, num_glyphs, substitute_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, substitute_len_list, substitute_glyphs_list));
     default:return_trace (false);
     }
   }
@@ -552,13 +528,10 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  unsigned int num_glyphs)
+		  hb_array_t<const GlyphID> glyphs)
   {
     TRACE_SERIALIZE (this);
-    if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternates.serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    return_trace (alternates.serialize (c, glyphs));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -625,21 +598,22 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<unsigned int> &alternate_len_list,
-		  unsigned int num_glyphs,
-		  hb_supplier_t<GlyphID> &alternate_glyphs_list)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const unsigned int> alternate_len_list,
+		  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!alternateSet.serialize (c, num_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_glyphs; i++)
-      if (unlikely (!alternateSet[i].serialize (c, this).serialize (c,
-								    alternate_glyphs_list,
-								    alternate_len_list[i]))) return_trace (false);
-    alternate_len_list += num_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, glyphs, num_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!alternateSet.serialize (c, glyphs.len))) return_trace (false);
+    for (unsigned int i = 0; i < glyphs.len; i++)
+    {
+      unsigned int alternate_len = alternate_len_list[i];
+      if (unlikely (!alternateSet[i].serialize (c, this)
+				    .serialize (c, alternate_glyphs_list.sub_array (0, alternate_len))))
+	return_trace (false);
+      alternate_glyphs_list += alternate_len;
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, glyphs));
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -670,17 +644,16 @@
 struct AlternateSubst
 {
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &glyphs,
-		  hb_supplier_t<unsigned int> &alternate_len_list,
-		  unsigned int num_glyphs,
-		  hb_supplier_t<GlyphID> &alternate_glyphs_list)
+		  hb_array_t<const GlyphID> glyphs,
+		  hb_array_t<const unsigned int> alternate_len_list,
+		  hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
     unsigned int format = 1;
     u.format.set (format);
     switch (u.format) {
-    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, num_glyphs, alternate_glyphs_list));
+    case 1: return_trace (u.format1.serialize (c, glyphs, alternate_len_list, alternate_glyphs_list));
     default:return_trace (false);
     }
   }
@@ -786,13 +759,12 @@
 
   bool serialize (hb_serialize_context_t *c,
 		  GlyphID ligature,
-		  hb_supplier_t<GlyphID> &components, /* Starting from second */
-		  unsigned int num_components /* Including first component */)
+		  hb_array_t<const GlyphID> components /* Starting from second */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
     ligGlyph = ligature;
-    if (unlikely (!component.serialize (c, components, num_components))) return_trace (false);
+    if (unlikely (!component.serialize (c, components))) return_trace (false);
     return_trace (true);
   }
 
@@ -867,21 +839,23 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &ligatures,
-		  hb_supplier_t<unsigned int> &component_count_list,
-		  unsigned int num_ligatures,
-		  hb_supplier_t<GlyphID> &component_list /* Starting from second for each ligature */)
+		  hb_array_t<const GlyphID> ligatures,
+		  hb_array_t<const unsigned int> component_count_list,
+		  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligature.serialize (c, num_ligatures))) return_trace (false);
-    for (unsigned int i = 0; i < num_ligatures; i++)
-      if (unlikely (!ligature[i].serialize (c, this).serialize (c,
-								ligatures[i],
-								component_list,
-								component_count_list[i]))) return_trace (false);
-    ligatures += num_ligatures;
-    component_count_list += num_ligatures;
+    if (unlikely (!ligature.serialize (c, ligatures.len))) return_trace (false);
+    for (unsigned int i = 0; i < ligatures.len; i++)
+    {
+      unsigned int component_count = MAX<int> (component_count_list[i] - 1, 0);
+      if (unlikely (!ligature[i].serialize (c, this)
+				.serialize (c,
+					    ligatures[i],
+					    component_list.sub_array (0, component_count))))
+	return_trace (false);
+      component_list += component_count;
+    }
     return_trace (true);
   }
 
@@ -965,25 +939,29 @@
   }
 
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &first_glyphs,
-		  hb_supplier_t<unsigned int> &ligature_per_first_glyph_count_list,
-		  unsigned int num_first_glyphs,
-		  hb_supplier_t<GlyphID> &ligatures_list,
-		  hb_supplier_t<unsigned int> &component_count_list,
-		  hb_supplier_t<GlyphID> &component_list /* Starting from second for each ligature */)
+		  hb_array_t<const GlyphID> first_glyphs,
+		  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+		  hb_array_t<const GlyphID> ligatures_list,
+		  hb_array_t<const unsigned int> component_count_list,
+		  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    if (unlikely (!ligatureSet.serialize (c, num_first_glyphs))) return_trace (false);
-    for (unsigned int i = 0; i < num_first_glyphs; i++)
-      if (unlikely (!ligatureSet[i].serialize (c, this).serialize (c,
-								   ligatures_list,
-								   component_count_list,
-								   ligature_per_first_glyph_count_list[i],
-								   component_list))) return_trace (false);
-    ligature_per_first_glyph_count_list += num_first_glyphs;
-    if (unlikely (!coverage.serialize (c, this).serialize (c, first_glyphs, num_first_glyphs))) return_trace (false);
-    return_trace (true);
+    if (unlikely (!ligatureSet.serialize (c, first_glyphs.len))) return_trace (false);
+    for (unsigned int i = 0; i < first_glyphs.len; i++)
+    {
+      unsigned int ligature_count = ligature_per_first_glyph_count_list[i];
+      if (unlikely (!ligatureSet[i].serialize (c, this)
+				   .serialize (c,
+					       ligatures_list.sub_array (0, ligature_count),
+					       component_count_list.sub_array (0, ligature_count),
+					       component_list))) return_trace (false);
+      ligatures_list += ligature_count;
+      component_count_list += ligature_count;
+      for (unsigned int i = 0; i < ligature_count; i++)
+	component_list += MAX<int> (component_count_list[i] - 1, 0);
+    }
+    return_trace (coverage.serialize (c, this).serialize (c, first_glyphs));
   }
 
   bool subset (hb_subset_context_t *c) const
@@ -1014,12 +992,11 @@
 struct LigatureSubst
 {
   bool serialize (hb_serialize_context_t *c,
-		  hb_supplier_t<GlyphID> &first_glyphs,
-		  hb_supplier_t<unsigned int> &ligature_per_first_glyph_count_list,
-		  unsigned int num_first_glyphs,
-		  hb_supplier_t<GlyphID> &ligatures_list,
-		  hb_supplier_t<unsigned int> &component_count_list,
-		  hb_supplier_t<GlyphID> &component_list /* Starting from second for each ligature */)
+		  hb_array_t<const GlyphID> first_glyphs,
+		  hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+		  hb_array_t<const GlyphID> ligatures_list,
+		  hb_array_t<const unsigned int> component_count_list,
+		  hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!c->extend_min (u.format))) return_trace (false);
@@ -1029,7 +1006,6 @@
     case 1: return_trace (u.format1.serialize (c,
 					       first_glyphs,
 					       ligature_per_first_glyph_count_list,
-					       num_first_glyphs,
 					       ligatures_list,
 					       component_count_list,
 					       component_list));
@@ -1372,62 +1348,55 @@
 
   bool serialize_single (hb_serialize_context_t *c,
 			 uint32_t lookup_props,
-		         hb_supplier_t<GlyphID> &glyphs,
-		         hb_supplier_t<GlyphID> &substitutes,
-		         unsigned int num_glyphs)
+		         hb_array_t<const GlyphID> glyphs,
+		         hb_array_t<const GlyphID> substitutes)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Single, lookup_props, 1))) return_trace (false);
-    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes, num_glyphs));
+    return_trace (serialize_subtable (c, 0).u.single.serialize (c, glyphs, substitutes));
   }
 
   bool serialize_multiple (hb_serialize_context_t *c,
 			   uint32_t lookup_props,
-			   hb_supplier_t<GlyphID> &glyphs,
-			   hb_supplier_t<unsigned int> &substitute_len_list,
-			   unsigned int num_glyphs,
-			   hb_supplier_t<GlyphID> &substitute_glyphs_list)
+			   hb_array_t<const GlyphID> glyphs,
+			   hb_array_t<const unsigned int> substitute_len_list,
+			   hb_array_t<const GlyphID> substitute_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Multiple, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.multiple.serialize (c,
 								  glyphs,
 								  substitute_len_list,
-								  num_glyphs,
 								  substitute_glyphs_list));
   }
 
   bool serialize_alternate (hb_serialize_context_t *c,
 			    uint32_t lookup_props,
-			    hb_supplier_t<GlyphID> &glyphs,
-			    hb_supplier_t<unsigned int> &alternate_len_list,
-			    unsigned int num_glyphs,
-			    hb_supplier_t<GlyphID> &alternate_glyphs_list)
+			    hb_array_t<const GlyphID> glyphs,
+			    hb_array_t<const unsigned int> alternate_len_list,
+			    hb_array_t<const GlyphID> alternate_glyphs_list)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Alternate, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.alternate.serialize (c,
 								   glyphs,
 								   alternate_len_list,
-								   num_glyphs,
 								   alternate_glyphs_list));
   }
 
   bool serialize_ligature (hb_serialize_context_t *c,
 			   uint32_t lookup_props,
-			   hb_supplier_t<GlyphID> &first_glyphs,
-			   hb_supplier_t<unsigned int> &ligature_per_first_glyph_count_list,
-			   unsigned int num_first_glyphs,
-			   hb_supplier_t<GlyphID> &ligatures_list,
-			   hb_supplier_t<unsigned int> &component_count_list,
-			   hb_supplier_t<GlyphID> &component_list /* Starting from second for each ligature */)
+			   hb_array_t<const GlyphID> first_glyphs,
+			   hb_array_t<const unsigned int> ligature_per_first_glyph_count_list,
+			   hb_array_t<const GlyphID> ligatures_list,
+			   hb_array_t<const unsigned int> component_count_list,
+			   hb_array_t<const GlyphID> component_list /* Starting from second for each ligature */)
   {
     TRACE_SERIALIZE (this);
     if (unlikely (!Lookup::serialize (c, SubTable::Ligature, lookup_props, 1))) return_trace (false);
     return_trace (serialize_subtable (c, 0).u.ligature.serialize (c,
 								  first_glyphs,
 								  ligature_per_first_glyph_count_list,
-								  num_first_glyphs,
 								  ligatures_list,
 								  component_count_list,
 								  component_list));
diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh
index ec472d0..2a1f2f8 100644
--- a/src/hb-ot-shape-complex-arabic-fallback.hh
+++ b/src/hb-ot-shape-complex-arabic-fallback.hh
@@ -79,8 +79,6 @@
    * May not be good-enough for presidential candidate interviews, but good-enough for us... */
   hb_stable_sort (&glyphs[0], num_glyphs, (int(*)(const OT::GlyphID*, const OT::GlyphID *)) OT::GlyphID::cmp, &substitutes[0]);
 
-  hb_supplier_t<OT::GlyphID> glyphs_supplier      (glyphs, num_glyphs);
-  hb_supplier_t<OT::GlyphID> substitutes_supplier (substitutes, num_glyphs);
 
   /* Each glyph takes four bytes max, and there's some overhead. */
   char buf[(SHAPING_TABLE_LAST - SHAPING_TABLE_FIRST + 1) * 4 + 128];
@@ -88,9 +86,8 @@
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_single (&c,
 				       OT::LookupFlag::IgnoreMarks,
-				       glyphs_supplier,
-				       substitutes_supplier,
-				       num_glyphs);
+				       hb_array (glyphs, num_glyphs),
+				       hb_array (substitutes, num_glyphs));
   c.end_serialize ();
   /* TODO sanitize the results? */
 
@@ -155,11 +152,6 @@
   if (!num_ligatures)
     return nullptr;
 
-  hb_supplier_t<OT::GlyphID>  first_glyphs_supplier                      (first_glyphs, num_first_glyphs);
-  hb_supplier_t<unsigned int> ligature_per_first_glyph_count_supplier    (ligature_per_first_glyph_count_list, num_first_glyphs);
-  hb_supplier_t<OT::GlyphID>  ligatures_supplier                         (ligature_list, num_ligatures);
-  hb_supplier_t<unsigned int> component_count_supplier                   (component_count_list, num_ligatures);
-  hb_supplier_t<OT::GlyphID>  component_supplier                         (component_list, num_ligatures);
 
   /* 16 bytes per ligature ought to be enough... */
   char buf[ARRAY_LENGTH_CONST (ligature_list) * 16 + 128];
@@ -167,12 +159,11 @@
   OT::SubstLookup *lookup = c.start_serialize<OT::SubstLookup> ();
   bool ret = lookup->serialize_ligature (&c,
 					 OT::LookupFlag::IgnoreMarks,
-					 first_glyphs_supplier,
-					 ligature_per_first_glyph_count_supplier,
-					 num_first_glyphs,
-					 ligatures_supplier,
-					 component_count_supplier,
-					 component_supplier);
+					 hb_array (first_glyphs, num_first_glyphs),
+					 hb_array (ligature_per_first_glyph_count_list, num_first_glyphs),
+					 hb_array (ligature_list, num_ligatures),
+					 hb_array (component_count_list, num_ligatures),
+					 hb_array (component_list, num_ligatures));
   c.end_serialize ();
   /* TODO sanitize the results? */