docs: protected TypeCodec<?> createCodec(GenericType<?> javaType, boolean isJavaCovariant) {
      TypeToken<?> token = javaType.__getToken();
      if (List.class.isAssignableFrom(token.getRawType())
          && token.getType() instanceof ParameterizedType) {
        Type[] typeArguments = ((ParameterizedType) token.getType()).getActualTypeArguments();
        GenericType<?> elementType = GenericType.of(typeArguments[0]);
        TypeCodec<?> elementCodec = codecFor(elementType, isJavaCovariant);
        return TypeCodecs.listOf(elementCodec);
      } else if (Set.class.isAssignableFrom(token.getRawType())
          && token.getType() instanceof ParameterizedType) {
        Type[] typeArguments = ((ParameterizedType) token.getType()).getActualTypeArguments();
        GenericType<?> elementType = GenericType.of(typeArguments[0]);
        TypeCodec<?> elementCodec = codecFor(elementType, isJavaCovariant);
        return TypeCodecs.setOf(elementCodec);
      } else if (Map.class.isAssignableFrom(token.getRawType())
          && token.getType() instanceof ParameterizedType) {
        Type[] typeArguments = ((ParameterizedType) token.getType()).getActualTypeArguments();
        GenericType<?> keyType = GenericType.of(typeArguments[0]);
        GenericType<?> valueType = GenericType.of(typeArguments[1]);
        TypeCodec<?> keyCodec = codecFor(keyType, isJavaCovariant);
        TypeCodec<?> valueCodec = codecFor(valueType, isJavaCovariant);
        return TypeCodecs.mapOf(keyCodec, valueCodec);
      }
      throw new CodecNotFoundException(null, javaType);
    }