class JSONStreamReader<T>
        extends StreamReader<T> {
    protected ObjectReaderAdapter objectReader;

    public JSONStreamReader(Type[] types) {
        super(types);
    }

    public JSONStreamReader(ObjectReaderAdapter objectReader) {
        this.objectReader = objectReader;
    }

    public static JSONStreamReader of(File file) throws IOException {
        return of(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8);
    }

    public static JSONStreamReader of(InputStream in) throws IOException {
        return of(in, StandardCharsets.UTF_8);
    }

    public static JSONStreamReader of(InputStream in, Type... types) throws IOException {
        return of(in, StandardCharsets.UTF_8, types);
    }

    public static JSONStreamReader of(InputStream in, Charset charset, Type... types) {
        if (charset == StandardCharsets.UTF_16 || charset == StandardCharsets.UTF_16LE || charset == StandardCharsets.UTF_16BE) {
            return new JSONStreamReaderUTF16(new InputStreamReader(in, charset), types);
        }
        return new JSONStreamReaderUTF8(in, charset, types);
    }

    public static JSONStreamReader of(InputStream in, Class objectClass) {
        return of(in, StandardCharsets.UTF_8, objectClass);
    }

    public static JSONStreamReader of(InputStream in, Charset charset, Class objectClass) {
        JSONReader.Context context = JSONFactory.createReadContext();
        ObjectReaderAdapter objectReader = (ObjectReaderAdapter) context.getObjectReader(objectClass);

        if (charset == StandardCharsets.UTF_16 || charset == StandardCharsets.UTF_16LE || charset == StandardCharsets.UTF_16BE) {
            return new JSONStreamReaderUTF16(new InputStreamReader(in, charset), objectReader);
        }
        return new JSONStreamReaderUTF8(in, charset, objectReader);
    }

    public ColumnStat getColumnStat(String name) {
        if (this.columnStatsMap == null) {
            this.columnStatsMap = new LinkedHashMap<>();
        }
        if (this.columns == null) {
            this.columns = new ArrayList<>();
        }
        if (columnStats == null) {
            columnStats = new ArrayList<>();
        }

        ColumnStat stat = columnStatsMap.get(name);
        if (stat == null && columnStatsMap.size() <= 100) {
            stat = new ColumnStat(name);
            columnStatsMap.put(name, stat);
            columns.add(name);
            columnStats.add(stat);
        }
        return stat;
    }

    protected static void stat(ColumnStat stat, Object value) {<FILL_FUNCTION_BODY>}

    public void statAll() {
        this.columnStatsMap = new LinkedHashMap<>();
        this.columns = new ArrayList<>();
        this.columnStats = new ArrayList<>();

        while (true) {
            Object object = readLineObject();
            if (object == null) {
                break;
            }

            statLine(object);
        }
    }

    public void statLine(Object object) {
        if (object instanceof Map) {
            statMap(null, (Map) object, 0);
        } else if (object instanceof List) {
            statArray(null, (List) object, 0);
        }
        rowCount++;
    }

    private void statArray(String parentKey, List list, int level) {
        if (level > 10) {
            return;
        }

        if (list.size() > 10) {
            return;
        }

        for (int i = 0; i < list.size(); i++) {
            Object item = list.get(i);
            String strKey = parentKey == null ? "[" + i + "]" : parentKey + "[" + i + "]";
            ColumnStat stat = getColumnStat(parentKey);
            stat(stat, item);

            if (item instanceof Map) {
                statMap(strKey, (Map) item, level + 1);
            } else if (item instanceof List) {
                statArray(strKey, (List) item, level + 1);
            }
        }
    }

    private void statMap(String parentKey, Map map, int level) {
        if (level > 10) {
            return;
        }

        for (Object o : map.entrySet()) {
            Map.Entry entry = (Map.Entry) o;
            Object key = entry.getKey();
            if (key instanceof String) {
                String strKey = parentKey == null ? (String) key : parentKey + "." + key;
                ColumnStat stat = getColumnStat(strKey);
                Object entryValue = entry.getValue();
                stat(stat, entryValue);

                if (entryValue instanceof Map) {
                    statMap(strKey, (Map) entryValue, level + 1);
                } else if (entryValue instanceof List) {
                    statArray(strKey, (List) entryValue, level + 1);
                }
            }
        }
    }
}

        if (stat == null) {
            return;
        }

        if (value == null) {
            stat.nulls++;
            return;
        }
        stat.values++;

        if (value instanceof Number) {
            stat.numbers++;

            if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
                stat.integers++;
            } else if (value instanceof Float || value instanceof Double) {
                stat.doubles++;
            }
            return;
        }

        if (value instanceof String) {
            stat.stat((String) value);
            return;
        }

        if (value instanceof Boolean) {
            stat.booleans++;
            return;
        }

        if (value instanceof Map) {
            stat.maps++;
            return;
        }

        if (value instanceof Collection) {
            stat.arrays++;
        }
    
<methods>public void <init>() ,public void <init>(java.lang.reflect.Type[]) ,public abstract T readLineObject() ,public Stream<T> stream() ,public Stream<T> stream(Class<T>) <variables>protected static final int SIZE_512K,protected List<com.alibaba.fastjson2.stream.StreamReader.ColumnStat> columnStats,protected Map<java.lang.String,com.alibaba.fastjson2.stream.StreamReader.ColumnStat> columnStatsMap,protected List<java.lang.String> columns,protected int end,protected int errorCount,protected long features,protected FieldReader#RAW[] fieldReaders,protected boolean inputEnd,protected int lineEnd,protected int lineNextStart,protected int lineSize,protected int lineStart,protected boolean lineTerminated,protected int[] mapping,protected Supplier#RAW objectCreator,protected int off,protected int rowCount,protected ObjectReader#RAW[] typeReaders,protected java.lang.reflect.Type[] types