/**
   * @param obj Object.
   * @return Bytes.
   * @throws org.apache.ignite.binary.BinaryObjectException If failed.
   */
  public byte[] marshal(@Nullable Object obj) throws BinaryObjectException {
    byte[] arr = portableMarsh.marshal(obj);

    assert arr.length > 0;

    return arr;
  }
  /** {@inheritDoc} */
  @Override
  public byte[] marshal(CacheObjectContext ctx, Object val) throws IgniteCheckedException {
    if (!((CacheObjectPortableContext) ctx).portableEnabled() || portableMarsh == null)
      return super.marshal(ctx, val);

    byte[] arr = portableMarsh.marshal(val);

    assert arr.length > 0;

    return arr;
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  @Override
  public Object marshalToPortable(@Nullable Object obj) throws BinaryObjectException {
    if (obj == null) return null;

    if (PortableUtils.isPortableType(obj.getClass())) return obj;

    if (obj instanceof Object[]) {
      Object[] arr = (Object[]) obj;

      Object[] pArr = new Object[arr.length];

      for (int i = 0; i < arr.length; i++) pArr[i] = marshalToPortable(arr[i]);

      return pArr;
    }

    if (obj instanceof IgniteBiTuple) {
      IgniteBiTuple tup = (IgniteBiTuple) obj;

      if (obj instanceof T2)
        return new T2<>(marshalToPortable(tup.get1()), marshalToPortable(tup.get2()));

      return new IgniteBiTuple<>(marshalToPortable(tup.get1()), marshalToPortable(tup.get2()));
    }

    if (obj instanceof Collection) {
      Collection<Object> col = (Collection<Object>) obj;

      Collection<Object> pCol;

      if (col instanceof Set) pCol = (Collection<Object>) PortableUtils.newSet((Set<?>) col);
      else pCol = new ArrayList<>(col.size());

      for (Object item : col) pCol.add(marshalToPortable(item));

      return pCol;
    }

    if (obj instanceof Map) {
      Map<?, ?> map = (Map<?, ?>) obj;

      Map<Object, Object> pMap = PortableUtils.newMap((Map<Object, Object>) obj);

      for (Map.Entry<?, ?> e : map.entrySet())
        pMap.put(marshalToPortable(e.getKey()), marshalToPortable(e.getValue()));

      return pMap;
    }

    if (obj instanceof Map.Entry) {
      Map.Entry<?, ?> e = (Map.Entry<?, ?>) obj;

      return new GridMapEntry<>(marshalToPortable(e.getKey()), marshalToPortable(e.getValue()));
    }

    byte[] arr = portableMarsh.marshal(obj);

    assert arr.length > 0;

    Object obj0 = portableMarsh.unmarshal(arr, null);

    // Possible if a class has writeObject method.
    if (obj0 instanceof BinaryObject) ((BinaryObjectImpl) obj0).detachAllowed(true);

    return obj0;
  }