@Override
 public void writeObject(Marshaller output, Object object) throws IOException {
   output.write(id);
   // Write as an unsigned, variable length, integer to safe space
   UnsignedNumeric.writeUnsignedInt(output, foreignId);
   externalizer.writeObject(output, object);
 }
 @Override
 public void writeObject(ObjectOutput output, OffHeapMetadataTransientCacheEntry ice)
     throws IOException {
   output.writeObject(ice.key);
   output.writeObject(ice.value);
   output.writeObject(ice.metadata);
   UnsignedNumeric.writeUnsignedLong(output, ice.lastUsed);
 }
 @Override
 public OffHeapMetadataTransientCacheEntry readObject(ObjectInput input)
     throws IOException, ClassNotFoundException {
   Object k = input.readObject();
   Object v = input.readObject();
   Metadata metadata = (Metadata) input.readObject();
   long lastUsed = UnsignedNumeric.readUnsignedLong(input);
   return new OffHeapMetadataTransientCacheEntry(k, v, metadata, lastUsed);
 }
  @Override
  public Set readObject(ObjectInput input) throws IOException, ClassNotFoundException {
    int magicNumber = input.readUnsignedByte();
    if (magicNumber == UNKNOWN_ENUM_SET) return (Set) input.readObject();

    AbstractSet<Enum> enumSet = null;
    int size = UnsignedNumeric.readUnsignedInt(input);
    for (int i = 0; i < size; i++) {
      switch (magicNumber) {
        case ENUM_SET:
        case REGULAR_ENUM_SET:
        case JUMBO_ENUM_SET:
          if (i == 0) enumSet = EnumSet.of((Enum) input.readObject());
          else enumSet.add((Enum) input.readObject());
          break;
      }
    }

    return enumSet;
  }
  @Override
  public Object readObject(Unmarshaller input) throws IOException, ClassNotFoundException {
    int readerIndex = input.readUnsignedByte();
    int foreignId = -1;
    if (readerIndex == Ids.MAX_ID) {
      // User defined externalizer
      foreignId = UnsignedNumeric.readUnsignedInt(input);
      readerIndex = generateForeignReaderIndex(foreignId);
    }

    ExternalizerAdapter adapter = readers.get(readerIndex);
    if (adapter == null) {
      if (!started) {
        log.tracef(
            "Either the marshaller has stopped or hasn't started. Read externalizers are not properly populated: %s",
            readers);

        if (Thread.currentThread().isInterrupted()) {
          throw log.pushReadInterruptionDueToCacheManagerShutdown(
              readerIndex, new InterruptedException());
        } else {
          throw log.cannotResolveExternalizerReader(gcr.getStatus(), readerIndex);
        }
      } else {
        if (log.isTraceEnabled()) {
          log.tracef("Unknown type. Input stream has %s to read", input.available());
          log.tracef("Check contents of read externalizers: %s", readers);
        }

        if (foreignId > 0) throw log.missingForeignExternalizer(foreignId);

        throw log.unknownExternalizerReaderIndex(readerIndex);
      }
    }

    return adapter.readObject(input);
  }