// Generated from jackson-core which is licensed under the Apache License 2.0.
// The following copyright from the original authors applies.
// See https://github.com/FasterXML/jackson-core/blob/2.14/LICENSE
//
// Copyright (c) 2007 - The Jackson Project Authors
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Autogenerated by jnigen. DO NOT EDIT!

// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name
// ignore_for_file: use_super_parameters

import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

import "JsonParser.dart" as jsonparser_;
import "../../../../_init.dart";

/// from: com.fasterxml.jackson.core.JsonFactory$Feature
///
/// Enumeration that defines all on/off features that can only be
/// changed for JsonFactory.
class JsonFactory_Feature extends jni.JObject {
  @override
  late final jni.JObjType<JsonFactory_Feature> $type = type;

  JsonFactory_Feature.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonFactory_FeatureType();
  static final _values =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonFactory_Feature__values")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonFactory_Feature> values() {
    return _values().object(const jni.JArrayType($JsonFactory_FeatureType()));
  }

  static final _valueOf = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonFactory_Feature__valueOf")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: static public com.fasterxml.jackson.core.JsonFactory.Feature valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonFactory_Feature valueOf(
    jni.JString name,
  ) {
    return _valueOf(name.reference.pointer)
        .object(const $JsonFactory_FeatureType());
  }

  static final _collectDefaults =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonFactory_Feature__collectDefaults")
          .asFunction<jni.JniResult Function()>();

  /// from: static public int collectDefaults()
  ///
  /// Method that calculates bit set (flags) of all features that
  /// are enabled by default.
  ///@return Bit field of features enabled by default
  static int collectDefaults() {
    return _collectDefaults().integer;
  }

  static final _enabledByDefault = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory_Feature__enabledByDefault")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean enabledByDefault()
  bool enabledByDefault() {
    return _enabledByDefault(reference.pointer).boolean;
  }

  static final _enabledIn = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int32)>>("JsonFactory_Feature__enabledIn")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: public boolean enabledIn(int flags)
  bool enabledIn(
    int flags,
  ) {
    return _enabledIn(reference.pointer, flags).boolean;
  }

  static final _getMask = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory_Feature__getMask")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getMask()
  int getMask() {
    return _getMask(reference.pointer).integer;
  }
}

final class $JsonFactory_FeatureType extends jni.JObjType<JsonFactory_Feature> {
  const $JsonFactory_FeatureType();

  @override
  String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory$Feature;";

  @override
  JsonFactory_Feature fromReference(jni.JReference reference) =>
      JsonFactory_Feature.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonFactory_FeatureType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonFactory_FeatureType) &&
        other is $JsonFactory_FeatureType;
  }
}

/// from: com.fasterxml.jackson.core.JsonFactory
///
/// The main factory class of Jackson package, used to configure and
/// construct reader (aka parser, JsonParser)
/// and writer (aka generator, JsonGenerator)
/// instances.
///
/// Factory instances are thread-safe and reusable after configuration
/// (if any). Typically applications and services use only a single
/// globally shared factory instance, unless they need differently
/// configured factories. Factory reuse is important if efficiency matters;
/// most recycling of expensive construct is done on per-factory basis.
///
/// Creation of a factory instance is a light-weight operation,
/// and since there is no need for pluggable alternative implementations
/// (as there is no "standard" JSON processor API to implement),
/// the default constructor is used for constructing factory
/// instances.
///@author Tatu Saloranta
class JsonFactory extends jni.JObject {
  @override
  late final jni.JObjType<JsonFactory> $type = type;

  JsonFactory.fromReference(
    jni.JReference reference,
  ) : super.fromReference(reference);

  /// The type which includes information such as the signature of this class.
  static const type = $JsonFactoryType();
  static final _get_FORMAT_NAME_JSON =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonFactory__FORMAT_NAME_JSON")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final java.lang.String FORMAT_NAME_JSON
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Name used to identify JSON format
  /// (and returned by \#getFormatName()
  static jni.JString get FORMAT_NAME_JSON =>
      _get_FORMAT_NAME_JSON().object(const jni.JStringType());

  static final _get_DEFAULT_FACTORY_FEATURE_FLAGS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonFactory__DEFAULT_FACTORY_FEATURE_FLAGS")
          .asFunction<jni.JniResult Function()>();

  /// from: static protected final int DEFAULT_FACTORY_FEATURE_FLAGS
  ///
  /// Bitfield (set of flags) of all factory features that are enabled by default.
  static int get DEFAULT_FACTORY_FEATURE_FLAGS =>
      _get_DEFAULT_FACTORY_FEATURE_FLAGS().integer;

  static final _get_DEFAULT_PARSER_FEATURE_FLAGS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonFactory__DEFAULT_PARSER_FEATURE_FLAGS")
          .asFunction<jni.JniResult Function()>();

  /// from: static protected final int DEFAULT_PARSER_FEATURE_FLAGS
  ///
  /// Bitfield (set of flags) of all parser features that are enabled
  /// by default.
  static int get DEFAULT_PARSER_FEATURE_FLAGS =>
      _get_DEFAULT_PARSER_FEATURE_FLAGS().integer;

  static final _get_DEFAULT_GENERATOR_FEATURE_FLAGS =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonFactory__DEFAULT_GENERATOR_FEATURE_FLAGS")
          .asFunction<jni.JniResult Function()>();

  /// from: static protected final int DEFAULT_GENERATOR_FEATURE_FLAGS
  ///
  /// Bitfield (set of flags) of all generator features that are enabled
  /// by default.
  static int get DEFAULT_GENERATOR_FEATURE_FLAGS =>
      _get_DEFAULT_GENERATOR_FEATURE_FLAGS().integer;

  static final _get_DEFAULT_ROOT_VALUE_SEPARATOR =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "get_JsonFactory__DEFAULT_ROOT_VALUE_SEPARATOR")
          .asFunction<jni.JniResult Function()>();

  /// from: static public final com.fasterxml.jackson.core.SerializableString DEFAULT_ROOT_VALUE_SEPARATOR
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JObject get DEFAULT_ROOT_VALUE_SEPARATOR =>
      _get_DEFAULT_ROOT_VALUE_SEPARATOR().object(const jni.JObjectType());

  static final _new0 = jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
          "JsonFactory__new0")
      .asFunction<jni.JniResult Function()>();

  /// from: public void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Default constructor used to create factory instances.
  /// Creation of a factory instance is a light-weight operation,
  /// but it is still a good idea to reuse limited number of
  /// factory instances (and quite often just a single instance):
  /// factories are used as context for storing some reused
  /// processing objects (such as symbol tables parsers use)
  /// and this reuse only works within context of a single
  /// factory instance.
  factory JsonFactory() {
    return JsonFactory.fromReference(_new0().reference);
  }

  static final _new1 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonFactory__new1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.fasterxml.jackson.core.ObjectCodec oc)
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonFactory.new1(
    jni.JObject oc,
  ) {
    return JsonFactory.fromReference(_new1(oc.reference.pointer).reference);
  }

  static final _new2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__new2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: protected void <init>(com.fasterxml.jackson.core.JsonFactory src, com.fasterxml.jackson.core.ObjectCodec codec)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor used when copy()ing a factory instance.
  ///@param src Original factory to copy settings from
  ///@param codec Databinding-level codec to use, if any
  ///@since 2.2.1
  factory JsonFactory.new2(
    JsonFactory src,
    jni.JObject codec,
  ) {
    return JsonFactory.fromReference(
        _new2(src.reference.pointer, codec.reference.pointer).reference);
  }

  static final _new3 = jniLookup<
              ffi
              .NativeFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>>(
          "JsonFactory__new3")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>)>();

  /// from: public void <init>(com.fasterxml.jackson.core.JsonFactoryBuilder b)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor used by JsonFactoryBuilder for instantiation.
  ///@param b Builder that contains settings to use
  ///@since 2.10
  factory JsonFactory.new3(
    jni.JObject b,
  ) {
    return JsonFactory.fromReference(_new3(b.reference.pointer).reference);
  }

  static final _new4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__new4")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// from: protected void <init>(com.fasterxml.jackson.core.TSFBuilder<?,?> b, boolean bogus)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Constructor for subtypes; needed to work around the fact that before 3.0,
  /// this factory has cumbersome dual role as generic type as well as actual
  /// implementation for json.
  ///@param b Builder that contains settings to use
  ///@param bogus Argument only needed to separate constructor signature; ignored
  factory JsonFactory.new4(
    jni.JObject b,
    bool bogus,
  ) {
    return JsonFactory.fromReference(
        _new4(b.reference.pointer, bogus ? 1 : 0).reference);
  }

  static final _rebuild = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__rebuild")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.TSFBuilder<?,?> rebuild()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that allows construction of differently configured factory, starting
  /// with settings of this factory.
  ///@return Builder instance to use
  ///@since 2.10
  jni.JObject rebuild() {
    return _rebuild(reference.pointer).object(const jni.JObjectType());
  }

  static final _builder =
      jniLookup<ffi.NativeFunction<jni.JniResult Function()>>(
              "JsonFactory__builder")
          .asFunction<jni.JniResult Function()>();

  /// from: static public com.fasterxml.jackson.core.TSFBuilder<?,?> builder()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Main factory method to use for constructing JsonFactory instances with
  /// different configuration: creates and returns a builder for collecting configuration
  /// settings; instance created by calling {@code build()} after all configuration
  /// set.
  ///
  /// NOTE: signature unfortunately does not expose true implementation type; this
  /// will be fixed in 3.0.
  ///@return Builder instance to use
  static jni.JObject builder() {
    return _builder().object(const jni.JObjectType());
  }

  static final _copy = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__copy")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.JsonFactory copy()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing a new JsonFactory that has
  /// the same settings as this instance, but is otherwise
  /// independent (i.e. nothing is actually shared, symbol tables
  /// are separate).
  /// Note that ObjectCodec reference is not copied but is
  /// set to null; caller typically needs to set it after calling
  /// this method. Reason for this is that the codec is used for
  /// callbacks, and assumption is that there is strict 1-to-1
  /// mapping between codec, factory. Caller has to, then, explicitly
  /// set codec after making the copy.
  ///@return Copy of this factory instance
  ///@since 2.1
  JsonFactory copy() {
    return _copy(reference.pointer).object(const $JsonFactoryType());
  }

  static final _readResolve = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__readResolve")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: protected java.lang.Object readResolve()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that we need to override to actually make restoration go
  /// through constructors etc: needed to allow JDK serializability of
  /// factory instances.
  ///
  /// Note: must be overridden by sub-classes as well.
  ///@return Newly constructed instance
  jni.JObject readResolve() {
    return _readResolve(reference.pointer).object(const jni.JObjectType());
  }

  static final _requiresPropertyOrdering = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__requiresPropertyOrdering")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean requiresPropertyOrdering()
  ///
  /// Introspection method that higher-level functionality may call
  /// to see whether underlying data format requires a stable ordering
  /// of object properties or not.
  /// This is usually used for determining
  /// whether to force a stable ordering (like alphabetic ordering by name)
  /// if no ordering if explicitly specified.
  ///
  /// Default implementation returns <code>false</code> as JSON does NOT
  /// require stable ordering. Formats that require ordering include positional
  /// textual formats like <code>CSV</code>, and schema-based binary formats
  /// like <code>Avro</code>.
  ///@return Whether format supported by this factory
  ///   requires Object properties to be ordered.
  ///@since 2.3
  bool requiresPropertyOrdering() {
    return _requiresPropertyOrdering(reference.pointer).boolean;
  }

  static final _canHandleBinaryNatively = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__canHandleBinaryNatively")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canHandleBinaryNatively()
  ///
  /// Introspection method that higher-level functionality may call
  /// to see whether underlying data format can read and write binary
  /// data natively; that is, embeded it as-is without using encodings
  /// such as Base64.
  ///
  /// Default implementation returns <code>false</code> as JSON does not
  /// support native access: all binary content must use Base64 encoding.
  /// Most binary formats (like Smile and Avro) support native binary content.
  ///@return Whether format supported by this factory
  ///    supports native binary content
  ///@since 2.3
  bool canHandleBinaryNatively() {
    return _canHandleBinaryNatively(reference.pointer).boolean;
  }

  static final _canUseCharArrays = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__canUseCharArrays")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canUseCharArrays()
  ///
  /// Introspection method that can be used by base factory to check
  /// whether access using <code>char[]</code> is something that actual
  /// parser implementations can take advantage of, over having to
  /// use java.io.Reader. Sub-types are expected to override
  /// definition; default implementation (suitable for JSON) alleges
  /// that optimization are possible; and thereby is likely to try
  /// to access java.lang.String content by first copying it into
  /// recyclable intermediate buffer.
  ///@return Whether access to decoded textual content can be efficiently
  ///   accessed using parser method {@code getTextCharacters()}.
  ///@since 2.4
  bool canUseCharArrays() {
    return _canUseCharArrays(reference.pointer).boolean;
  }

  static final _canParseAsync = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__canParseAsync")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean canParseAsync()
  ///
  /// Introspection method that can be used to check whether this
  /// factory can create non-blocking parsers: parsers that do not
  /// use blocking I/O abstractions but instead use a
  /// com.fasterxml.jackson.core.async.NonBlockingInputFeeder.
  ///@return Whether this factory supports non-blocking ("async") parsing or
  ///    not (and consequently whether {@code createNonBlockingXxx()} method(s) work)
  ///@since 2.9
  bool canParseAsync() {
    return _canParseAsync(reference.pointer).boolean;
  }

  static final _getFormatReadFeatureType = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getFormatReadFeatureType")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatReadFeatureType()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject getFormatReadFeatureType() {
    return _getFormatReadFeatureType(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _getFormatWriteFeatureType = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getFormatWriteFeatureType")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.Class<? extends com.fasterxml.jackson.core.FormatFeature> getFormatWriteFeatureType()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject getFormatWriteFeatureType() {
    return _getFormatWriteFeatureType(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _canUseSchema = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__canUseSchema")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method that can be used to quickly check whether given schema
  /// is something that parsers and/or generators constructed by this
  /// factory could use. Note that this means possible use, at the level
  /// of data format (i.e. schema is for same data format as parsers and
  /// generators this factory constructs); individual schema instances
  /// may have further usage restrictions.
  ///@param schema Schema instance to check
  ///@return Whether parsers and generators constructed by this factory
  ///   can use specified format schema instance
  bool canUseSchema(
    jni.JObject schema,
  ) {
    return _canUseSchema(reference.pointer, schema.reference.pointer).boolean;
  }

  static final _getFormatName = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getFormatName")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String getFormatName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that returns short textual id identifying format
  /// this factory supports.
  ///
  /// Note: sub-classes should override this method; default
  /// implementation will return null for all sub-classes
  ///@return Name of the format handled by parsers, generators this factory creates
  jni.JString getFormatName() {
    return _getFormatName(reference.pointer).object(const jni.JStringType());
  }

  static final _hasFormat = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__hasFormat")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.format.MatchStrength hasFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject hasFormat(
    jni.JObject acc,
  ) {
    return _hasFormat(reference.pointer, acc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _requiresCustomCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__requiresCustomCodec")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public boolean requiresCustomCodec()
  ///
  /// Method that can be called to determine if a custom
  /// ObjectCodec is needed for binding data parsed
  /// using JsonParser constructed by this factory
  /// (which typically also implies the same for serialization
  /// with JsonGenerator).
  ///@return True if custom codec is needed with parsers and
  ///   generators created by this factory; false if a general
  ///   ObjectCodec is enough
  ///@since 2.1
  bool requiresCustomCodec() {
    return _requiresCustomCodec(reference.pointer).boolean;
  }

  static final _hasJSONFormat = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__hasJSONFormat")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: protected com.fasterxml.jackson.core.format.MatchStrength hasJSONFormat(com.fasterxml.jackson.core.format.InputAccessor acc)
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject hasJSONFormat(
    jni.JObject acc,
  ) {
    return _hasJSONFormat(reference.pointer, acc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _version = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__version")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.Version version()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject version() {
    return _version(reference.pointer).object(const jni.JObjectType());
  }

  static final _configure = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonFactory.Feature f, boolean state)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling or disabling specified parser feature
  /// (check JsonParser.Feature for list of features)
  ///@param f Feature to enable/disable
  ///@param state Whether to enable or disable the feature
  ///@return This factory instance (to allow call chaining)
  ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
  JsonFactory configure(
    JsonFactory_Feature f,
    bool state,
  ) {
    return _configure(reference.pointer, f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _enable = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__enable")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonFactory.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling specified parser feature
  /// (check JsonFactory.Feature for list of features)
  ///@param f Feature to enable
  ///@return This factory instance (to allow call chaining)
  ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
  JsonFactory enable(
    JsonFactory_Feature f,
  ) {
    return _enable(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _disable = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__disable")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonFactory.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for disabling specified parser features
  /// (check JsonFactory.Feature for list of features)
  ///@param f Feature to disable
  ///@return This factory instance (to allow call chaining)
  ///@deprecated since 2.10 use JsonFactoryBuilder\#configure(JsonFactory.Feature, boolean) instead
  JsonFactory disable(
    JsonFactory_Feature f,
  ) {
    return _disable(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _isEnabled = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonFactory.Feature f)
  ///
  /// Checked whether specified parser feature is enabled.
  ///@param f Feature to check
  ///@return True if the specified feature is enabled
  bool isEnabled(
    JsonFactory_Feature f,
  ) {
    return _isEnabled(reference.pointer, f.reference.pointer).boolean;
  }

  static final _getParserFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getParserFeatures")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public final int getParserFeatures()
  int getParserFeatures() {
    return _getParserFeatures(reference.pointer).integer;
  }

  static final _getGeneratorFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getGeneratorFeatures")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public final int getGeneratorFeatures()
  int getGeneratorFeatures() {
    return _getGeneratorFeatures(reference.pointer).integer;
  }

  static final _getFormatParserFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getFormatParserFeatures")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getFormatParserFeatures()
  int getFormatParserFeatures() {
    return _getFormatParserFeatures(reference.pointer).integer;
  }

  static final _getFormatGeneratorFeatures = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getFormatGeneratorFeatures")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public int getFormatGeneratorFeatures()
  int getFormatGeneratorFeatures() {
    return _getFormatGeneratorFeatures(reference.pointer).integer;
  }

  static final _configure1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonParser.Feature f, boolean state)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling or disabling specified parser feature
  /// (check JsonParser.Feature for list of features)
  ///@param f Feature to enable/disable
  ///@param state Whether to enable or disable the feature
  ///@return This factory instance (to allow call chaining)
  JsonFactory configure1(
    jsonparser_.JsonParser_Feature f,
    bool state,
  ) {
    return _configure1(reference.pointer, f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _enable1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__enable1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonParser.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling specified parser feature
  /// (check JsonParser.Feature for list of features)
  ///@param f Feature to enable
  ///@return This factory instance (to allow call chaining)
  JsonFactory enable1(
    jsonparser_.JsonParser_Feature f,
  ) {
    return _enable1(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _disable1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__disable1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonParser.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for disabling specified parser features
  /// (check JsonParser.Feature for list of features)
  ///@param f Feature to disable
  ///@return This factory instance (to allow call chaining)
  JsonFactory disable1(
    jsonparser_.JsonParser_Feature f,
  ) {
    return _disable1(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _isEnabled1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
  ///
  /// Method for checking if the specified parser feature is enabled.
  ///@param f Feature to check
  ///@return True if specified feature is enabled
  bool isEnabled1(
    jsonparser_.JsonParser_Feature f,
  ) {
    return _isEnabled1(reference.pointer, f.reference.pointer).boolean;
  }

  static final _isEnabled2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
  ///
  /// Method for checking if the specified stream read feature is enabled.
  ///@param f Feature to check
  ///@return True if specified feature is enabled
  ///@since 2.10
  bool isEnabled2(
    jni.JObject f,
  ) {
    return _isEnabled2(reference.pointer, f.reference.pointer).boolean;
  }

  static final _getInputDecorator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getInputDecorator")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.io.InputDecorator getInputDecorator()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for getting currently configured input decorator (if any;
  /// there is no default decorator).
  ///@return InputDecorator configured, if any
  jni.JObject getInputDecorator() {
    return _getInputDecorator(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _setInputDecorator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__setInputDecorator")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory setInputDecorator(com.fasterxml.jackson.core.io.InputDecorator d)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for overriding currently configured input decorator
  ///@param d Decorator to configure for this factory, if any ({@code null} if none)
  ///@return This factory instance (to allow call chaining)
  ///@deprecated Since 2.10 use JsonFactoryBuilder\#inputDecorator(InputDecorator) instead
  JsonFactory setInputDecorator(
    jni.JObject d,
  ) {
    return _setInputDecorator(reference.pointer, d.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _configure2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>, ffi.Uint8)>>("JsonFactory__configure2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int)>();

  /// from: public final com.fasterxml.jackson.core.JsonFactory configure(com.fasterxml.jackson.core.JsonGenerator.Feature f, boolean state)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling or disabling specified generator feature
  /// (check JsonGenerator.Feature for list of features)
  ///@param f Feature to enable/disable
  ///@param state Whether to enable or disable the feature
  ///@return This factory instance (to allow call chaining)
  JsonFactory configure2(
    jni.JObject f,
    bool state,
  ) {
    return _configure2(reference.pointer, f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _enable2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__enable2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory enable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for enabling specified generator features
  /// (check JsonGenerator.Feature for list of features)
  ///@param f Feature to enable
  ///@return This factory instance (to allow call chaining)
  JsonFactory enable2(
    jni.JObject f,
  ) {
    return _enable2(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _disable2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__disable2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory disable(com.fasterxml.jackson.core.JsonGenerator.Feature f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for disabling specified generator feature
  /// (check JsonGenerator.Feature for list of features)
  ///@param f Feature to disable
  ///@return This factory instance (to allow call chaining)
  JsonFactory disable2(
    jni.JObject f,
  ) {
    return _disable2(reference.pointer, f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _isEnabled3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled3")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final boolean isEnabled(com.fasterxml.jackson.core.JsonGenerator.Feature f)
  ///
  /// Check whether specified generator feature is enabled.
  ///@param f Feature to check
  ///@return Whether specified feature is enabled
  bool isEnabled3(
    jni.JObject f,
  ) {
    return _isEnabled3(reference.pointer, f.reference.pointer).boolean;
  }

  static final _isEnabled4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__isEnabled4")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public final boolean isEnabled(com.fasterxml.jackson.core.StreamWriteFeature f)
  ///
  /// Check whether specified stream write feature is enabled.
  ///@param f Feature to check
  ///@return Whether specified feature is enabled
  ///@since 2.10
  bool isEnabled4(
    jni.JObject f,
  ) {
    return _isEnabled4(reference.pointer, f.reference.pointer).boolean;
  }

  static final _getCharacterEscapes = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getCharacterEscapes")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.io.CharacterEscapes getCharacterEscapes()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for accessing custom escapes factory uses for JsonGenerators
  /// it creates.
  ///@return Configured {@code CharacterEscapes}, if any; {@code null} if none
  jni.JObject getCharacterEscapes() {
    return _getCharacterEscapes(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _setCharacterEscapes = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__setCharacterEscapes")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory setCharacterEscapes(com.fasterxml.jackson.core.io.CharacterEscapes esc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for defining custom escapes factory uses for JsonGenerators
  /// it creates.
  ///@param esc CharaterEscapes to set (or {@code null} for "none")
  ///@return This factory instance (to allow call chaining)
  JsonFactory setCharacterEscapes(
    jni.JObject esc,
  ) {
    return _setCharacterEscapes(reference.pointer, esc.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _getOutputDecorator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getOutputDecorator")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.io.OutputDecorator getOutputDecorator()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for getting currently configured output decorator (if any;
  /// there is no default decorator).
  ///@return OutputDecorator configured for generators factory creates, if any;
  ///    {@code null} if none.
  jni.JObject getOutputDecorator() {
    return _getOutputDecorator(reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _setOutputDecorator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__setOutputDecorator")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory setOutputDecorator(com.fasterxml.jackson.core.io.OutputDecorator d)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for overriding currently configured output decorator
  ///@return This factory instance (to allow call chaining)
  ///@param d Output decorator to use, if any
  ///@deprecated Since 2.10 use JsonFactoryBuilder\#outputDecorator(OutputDecorator) instead
  JsonFactory setOutputDecorator(
    jni.JObject d,
  ) {
    return _setOutputDecorator(reference.pointer, d.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _setRootValueSeparator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__setRootValueSeparator")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory setRootValueSeparator(java.lang.String sep)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that allows overriding String used for separating root-level
  /// JSON values (default is single space character)
  ///@param sep Separator to use, if any; null means that no separator is
  ///   automatically added
  ///@return This factory instance (to allow call chaining)
  JsonFactory setRootValueSeparator(
    jni.JString sep,
  ) {
    return _setRootValueSeparator(reference.pointer, sep.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _getRootValueSeparator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getRootValueSeparator")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public java.lang.String getRootValueSeparator()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// @return Root value separator configured, if any
  jni.JString getRootValueSeparator() {
    return _getRootValueSeparator(reference.pointer)
        .object(const jni.JStringType());
  }

  static final _setCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__setCodec")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonFactory setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for associating a ObjectCodec (typically
  /// a <code>com.fasterxml.jackson.databind.ObjectMapper</code>)
  /// with this factory (and more importantly, parsers and generators
  /// it constructs). This is needed to use data-binding methods
  /// of JsonParser and JsonGenerator instances.
  ///@param oc Codec to use
  ///@return This factory instance (to allow call chaining)
  JsonFactory setCodec(
    jni.JObject oc,
  ) {
    return _setCodec(reference.pointer, oc.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _getCodec = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__getCodec")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.ObjectCodec getCodec()
  /// The returned object must be released after use, by calling the [release] method.
  jni.JObject getCodec() {
    return _getCodec(reference.pointer).object(const jni.JObjectType());
  }

  static final _createParser = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.File f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// contents of specified file.
  ///
  ///
  /// Encoding is auto-detected from contents according to JSON
  /// specification recommended mechanism. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///
  ///
  /// Underlying input stream (needed for reading contents)
  /// will be __owned__ (and managed, i.e. closed as need be) by
  /// the parser, since caller has no access to it.
  ///@param f File that contains JSON content to parse
  ///@since 2.1
  jsonparser_.JsonParser createParser(
    jni.JObject f,
  ) {
    return _createParser(reference.pointer, f.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.net.URL url)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// contents of resource reference by given URL.
  ///
  /// Encoding is auto-detected from contents according to JSON
  /// specification recommended mechanism. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///
  /// Underlying input stream (needed for reading contents)
  /// will be __owned__ (and managed, i.e. closed as need be) by
  /// the parser, since caller has no access to it.
  ///@param url URL pointing to resource that contains JSON content to parse
  ///@since 2.1
  jsonparser_.JsonParser createParser1(
    jni.JObject url,
  ) {
    return _createParser1(reference.pointer, url.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.InputStream in)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// the contents accessed via specified input stream.
  ///
  /// The input stream will __not be owned__ by
  /// the parser, it will still be managed (i.e. closed if
  /// end-of-stream is reacher, or parser close method called)
  /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
  /// is enabled.
  ///
  ///
  /// Note: no encoding argument is taken since it can always be
  /// auto-detected as suggested by JSON RFC. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///@param in InputStream to use for reading JSON content to parse
  ///@since 2.1
  jsonparser_.JsonParser createParser2(
    jni.JObject in0,
  ) {
    return _createParser2(reference.pointer, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser3")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.Reader r)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// the contents accessed via specified Reader.
  ///
  /// The read stream will __not be owned__ by
  /// the parser, it will still be managed (i.e. closed if
  /// end-of-stream is reacher, or parser close method called)
  /// if (and only if) com.fasterxml.jackson.core.StreamReadFeature\#AUTO_CLOSE_SOURCE
  /// is enabled.
  ///@param r Reader to use for reading JSON content to parse
  ///@since 2.1
  jsonparser_.JsonParser createParser3(
    jni.JObject r,
  ) {
    return _createParser3(reference.pointer, r.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser4")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// the contents of given byte array.
  ///@since 2.1
  jsonparser_.JsonParser createParser4(
    jni.JArray<jni.jbyte> data,
  ) {
    return _createParser4(reference.pointer, data.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser5 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32)>>("JsonFactory__createParser5")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(byte[] data, int offset, int len)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// the contents of given byte array.
  ///@param data Buffer that contains data to parse
  ///@param offset Offset of the first data byte within buffer
  ///@param len Length of contents to parse within buffer
  ///@since 2.1
  jsonparser_.JsonParser createParser5(
    jni.JArray<jni.jbyte> data,
    int offset,
    int len,
  ) {
    return _createParser5(
            reference.pointer, data.reference.pointer, offset, len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser6 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser6")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.lang.String content)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// contents of given String.
  ///@since 2.1
  jsonparser_.JsonParser createParser6(
    jni.JString content,
  ) {
    return _createParser6(reference.pointer, content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser7 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser7")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// contents of given char array.
  ///@since 2.4
  jsonparser_.JsonParser createParser7(
    jni.JArray<jni.jchar> content,
  ) {
    return _createParser7(reference.pointer, content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser8 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32)>>("JsonFactory__createParser8")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(char[] content, int offset, int len)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing contents of given char array.
  ///@since 2.4
  jsonparser_.JsonParser createParser8(
    jni.JArray<jni.jchar> content,
    int offset,
    int len,
  ) {
    return _createParser8(
            reference.pointer, content.reference.pointer, offset, len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createParser9 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createParser9")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createParser(java.io.DataInput in)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Optional method for constructing parser for reading contents from specified DataInput
  /// instance.
  ///
  /// If this factory does not support DataInput as source,
  /// will throw UnsupportedOperationException
  ///@since 2.8
  jsonparser_.JsonParser createParser9(
    jni.JObject in0,
  ) {
    return _createParser9(reference.pointer, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createNonBlockingByteArrayParser = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
              )>>("JsonFactory__createNonBlockingByteArrayParser")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
          )>();

  /// from: public com.fasterxml.jackson.core.JsonParser createNonBlockingByteArrayParser()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Optional method for constructing parser for non-blocking parsing
  /// via com.fasterxml.jackson.core.async.ByteArrayFeeder
  /// interface (accessed using JsonParser\#getNonBlockingInputFeeder()
  /// from constructed instance).
  ///
  /// If this factory does not support non-blocking parsing (either at all,
  /// or from byte array),
  /// will throw UnsupportedOperationException.
  ///
  /// Note that JSON-backed factory only supports parsing of UTF-8 encoded JSON content
  /// (and US-ASCII since it is proper subset); other encodings are not supported
  /// at this point.
  ///@since 2.9
  jsonparser_.JsonParser createNonBlockingByteArrayParser() {
    return _createNonBlockingByteArrayParser(reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createGenerator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON generator for writing JSON content
  /// using specified output stream.
  /// Encoding to use must be specified, and needs to be one of available
  /// types (as per JSON specification).
  ///
  /// Underlying stream __is NOT owned__ by the generator constructed,
  /// so that generator will NOT close the output stream when
  /// JsonGenerator\#close is called (unless auto-closing
  /// feature,
  /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
  /// is enabled).
  /// Using application needs to close it explicitly if this is the case.
  ///
  /// Note: there are formats that use fixed encoding (like most binary data formats)
  /// and that ignore passed in encoding.
  ///@param out OutputStream to use for writing JSON content
  ///@param enc Character encoding to use
  ///@since 2.1
  jni.JObject createGenerator(
    jni.JObject out,
    jni.JObject enc,
  ) {
    return _createGenerator(
            reference.pointer, out.reference.pointer, enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createGenerator1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.OutputStream out)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Convenience method for constructing generator that uses default
  /// encoding of the format (UTF-8 for JSON and most other data formats).
  ///
  /// Note: there are formats that use fixed encoding (like most binary data formats).
  ///@since 2.1
  jni.JObject createGenerator1(
    jni.JObject out,
  ) {
    return _createGenerator1(reference.pointer, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createGenerator2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.Writer w)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON generator for writing JSON content
  /// using specified Writer.
  ///
  /// Underlying stream __is NOT owned__ by the generator constructed,
  /// so that generator will NOT close the Reader when
  /// JsonGenerator\#close is called (unless auto-closing
  /// feature,
  /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
  /// Using application needs to close it explicitly.
  ///@since 2.1
  ///@param w Writer to use for writing JSON content
  jni.JObject createGenerator2(
    jni.JObject w,
  ) {
    return _createGenerator2(reference.pointer, w.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createGenerator3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator3")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.File f, com.fasterxml.jackson.core.JsonEncoding enc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON generator for writing JSON content
  /// to specified file, overwriting contents it might have (or creating
  /// it if such file does not yet exist).
  /// Encoding to use must be specified, and needs to be one of available
  /// types (as per JSON specification).
  ///
  /// Underlying stream __is owned__ by the generator constructed,
  /// i.e. generator will handle closing of file when
  /// JsonGenerator\#close is called.
  ///@param f File to write contents to
  ///@param enc Character encoding to use
  ///@since 2.1
  jni.JObject createGenerator3(
    jni.JObject f,
    jni.JObject enc,
  ) {
    return _createGenerator3(
            reference.pointer, f.reference.pointer, enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createGenerator4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator4")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out, com.fasterxml.jackson.core.JsonEncoding enc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing generator for writing content using specified
  /// DataOutput instance.
  ///@since 2.8
  jni.JObject createGenerator4(
    jni.JObject out,
    jni.JObject enc,
  ) {
    return _createGenerator4(
            reference.pointer, out.reference.pointer, enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createGenerator5 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createGenerator5")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createGenerator(java.io.DataOutput out)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Convenience method for constructing generator that uses default
  /// encoding of the format (UTF-8 for JSON and most other data formats).
  ///
  /// Note: there are formats that use fixed encoding (like most binary data formats).
  ///@since 2.8
  jni.JObject createGenerator5(
    jni.JObject out,
  ) {
    return _createGenerator5(reference.pointer, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createJsonParser = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.File f)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// contents of specified file.
  ///
  /// Encoding is auto-detected from contents according to JSON
  /// specification recommended mechanism. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///
  ///
  /// Underlying input stream (needed for reading contents)
  /// will be __owned__ (and managed, i.e. closed as need be) by
  /// the parser, since caller has no access to it.
  ///@param f File that contains JSON content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(File) instead.
  jsonparser_.JsonParser createJsonParser(
    jni.JObject f,
  ) {
    return _createJsonParser(reference.pointer, f.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.net.URL url)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// contents of resource reference by given URL.
  ///
  /// Encoding is auto-detected from contents according to JSON
  /// specification recommended mechanism. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///
  /// Underlying input stream (needed for reading contents)
  /// will be __owned__ (and managed, i.e. closed as need be) by
  /// the parser, since caller has no access to it.
  ///@param url URL pointing to resource that contains JSON content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(URL) instead.
  jsonparser_.JsonParser createJsonParser1(
    jni.JObject url,
  ) {
    return _createJsonParser1(reference.pointer, url.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.InputStream in)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON parser instance to parse
  /// the contents accessed via specified input stream.
  ///
  /// The input stream will __not be owned__ by
  /// the parser, it will still be managed (i.e. closed if
  /// end-of-stream is reacher, or parser close method called)
  /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
  /// is enabled.
  ///
  ///
  /// Note: no encoding argument is taken since it can always be
  /// auto-detected as suggested by JSON RFC. Json specification
  /// supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
  /// so auto-detection implemented only for this charsets.
  /// For other charsets use \#createParser(java.io.Reader).
  ///@param in InputStream to use for reading JSON content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(InputStream) instead.
  jsonparser_.JsonParser createJsonParser2(
    jni.JObject in0,
  ) {
    return _createJsonParser2(reference.pointer, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser3 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser3")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.io.Reader r)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// the contents accessed via specified Reader.
  ///
  /// The read stream will __not be owned__ by
  /// the parser, it will still be managed (i.e. closed if
  /// end-of-stream is reacher, or parser close method called)
  /// if (and only if) com.fasterxml.jackson.core.JsonParser.Feature\#AUTO_CLOSE_SOURCE
  /// is enabled.
  ///@param r Reader to use for reading JSON content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(Reader) instead.
  jsonparser_.JsonParser createJsonParser3(
    jni.JObject r,
  ) {
    return _createJsonParser3(reference.pointer, r.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser4 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser4")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing the contents of given byte array.
  ///@param data Input content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(byte[]) instead.
  jsonparser_.JsonParser createJsonParser4(
    jni.JArray<jni.jbyte> data,
  ) {
    return _createJsonParser4(reference.pointer, data.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser5 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Int32,
                  ffi.Int32)>>("JsonFactory__createJsonParser5")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>, int, int)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(byte[] data, int offset, int len)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// the contents of given byte array.
  ///@param data Buffer that contains data to parse
  ///@param offset Offset of the first data byte within buffer
  ///@param len Length of contents to parse within buffer
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(byte[],int,int) instead.
  jsonparser_.JsonParser createJsonParser5(
    jni.JArray<jni.jbyte> data,
    int offset,
    int len,
  ) {
    return _createJsonParser5(
            reference.pointer, data.reference.pointer, offset, len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonParser6 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonParser6")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonParser createJsonParser(java.lang.String content)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing parser for parsing
  /// contents of given String.
  ///@param content Input content to parse
  ///@return Parser constructed
  ///@throws IOException if parser initialization fails due to I/O (read) problem
  ///@throws JsonParseException if parser initialization fails due to content decoding problem
  ///@deprecated Since 2.2, use \#createParser(String) instead.
  jsonparser_.JsonParser createJsonParser6(
    jni.JString content,
  ) {
    return _createJsonParser6(reference.pointer, content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _createJsonGenerator = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>,
              ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out, com.fasterxml.jackson.core.JsonEncoding enc)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON generator for writing JSON content
  /// using specified output stream.
  /// Encoding to use must be specified, and needs to be one of available
  /// types (as per JSON specification).
  ///
  /// Underlying stream __is NOT owned__ by the generator constructed,
  /// so that generator will NOT close the output stream when
  /// JsonGenerator\#close is called (unless auto-closing
  /// feature,
  /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET
  /// is enabled).
  /// Using application needs to close it explicitly if this is the case.
  ///
  /// Note: there are formats that use fixed encoding (like most binary data formats)
  /// and that ignore passed in encoding.
  ///@param out OutputStream to use for writing JSON content
  ///@param enc Character encoding to use
  ///@return Generator constructed
  ///@throws IOException if parser initialization fails due to I/O (write) problem
  ///@deprecated Since 2.2, use \#createGenerator(OutputStream, JsonEncoding) instead.
  jni.JObject createJsonGenerator(
    jni.JObject out,
    jni.JObject enc,
  ) {
    return _createJsonGenerator(
            reference.pointer, out.reference.pointer, enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createJsonGenerator1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator1")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.Writer out)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for constructing JSON generator for writing JSON content
  /// using specified Writer.
  ///
  /// Underlying stream __is NOT owned__ by the generator constructed,
  /// so that generator will NOT close the Reader when
  /// JsonGenerator\#close is called (unless auto-closing
  /// feature,
  /// com.fasterxml.jackson.core.JsonGenerator.Feature\#AUTO_CLOSE_TARGET is enabled).
  /// Using application needs to close it explicitly.
  ///@param out Writer to use for writing JSON content
  ///@return Generator constructed
  ///@throws IOException if parser initialization fails due to I/O (write) problem
  ///@deprecated Since 2.2, use \#createGenerator(Writer) instead.
  jni.JObject createJsonGenerator1(
    jni.JObject out,
  ) {
    return _createJsonGenerator1(reference.pointer, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _createJsonGenerator2 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Pointer<ffi.Void>)>>("JsonFactory__createJsonGenerator2")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, ffi.Pointer<ffi.Void>)>();

  /// from: public com.fasterxml.jackson.core.JsonGenerator createJsonGenerator(java.io.OutputStream out)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Convenience method for constructing generator that uses default
  /// encoding of the format (UTF-8 for JSON and most other data formats).
  ///
  /// Note: there are formats that use fixed encoding (like most binary data formats).
  ///@param out OutputStream to use for writing JSON content
  ///@return Generator constructed
  ///@throws IOException if parser initialization fails due to I/O (write) problem
  ///@deprecated Since 2.2, use \#createGenerator(OutputStream) instead.
  jni.JObject createJsonGenerator2(
    jni.JObject out,
  ) {
    return _createJsonGenerator2(reference.pointer, out.reference.pointer)
        .object(const jni.JObjectType());
  }
}

final class $JsonFactoryType extends jni.JObjType<JsonFactory> {
  const $JsonFactoryType();

  @override
  String get signature => r"Lcom/fasterxml/jackson/core/JsonFactory;";

  @override
  JsonFactory fromReference(jni.JReference reference) =>
      JsonFactory.fromReference(reference);

  @override
  jni.JObjType get superType => const jni.JObjectType();

  @override
  final superCount = 1;

  @override
  int get hashCode => ($JsonFactoryType).hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($JsonFactoryType) && other is $JsonFactoryType;
  }
}
