// 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_;

/// 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);

  static final _class =
      jni.JClass.forName(r"com/fasterxml/jackson/core/JsonFactory$Feature");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonFactory_FeatureType();
  static final _id_values = _class.staticMethodId(
    r"values",
    r"()[Lcom/fasterxml/jackson/core/JsonFactory$Feature;",
  );

  static final _values = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallStaticObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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(_class.reference.pointer, _id_values as jni.JMethodIDPtr)
        .object(const jni.JArrayType($JsonFactory_FeatureType()));
  }

  static final _id_valueOf = _class.staticMethodId(
    r"valueOf",
    r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory$Feature;",
  );

  static final _valueOf = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallStaticObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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(_class.reference.pointer, _id_valueOf as jni.JMethodIDPtr,
            name.reference.pointer)
        .object(const $JsonFactory_FeatureType());
  }

  static final _id_collectDefaults = _class.staticMethodId(
    r"collectDefaults",
    r"()I",
  );

  static final _collectDefaults = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallStaticIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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(
            _class.reference.pointer, _id_collectDefaults as jni.JMethodIDPtr)
        .integer;
  }

  static final _id_enabledByDefault = _class.instanceMethodId(
    r"enabledByDefault",
    r"()Z",
  );

  static final _enabledByDefault = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public boolean enabledByDefault()
  bool enabledByDefault() {
    return _enabledByDefault(
            reference.pointer, _id_enabledByDefault as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_enabledIn = _class.instanceMethodId(
    r"enabledIn",
    r"(I)Z",
  );

  static final _enabledIn = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
                  ffi.VarArgs<(ffi.Int64,)>)>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
              ffi.Pointer<ffi.Void>, jni.JMethodIDPtr, int)>();

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

  static final _id_getMask = _class.instanceMethodId(
    r"getMask",
    r"()I",
  );

  static final _getMask = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public int getMask()
  int getMask() {
    return _getMask(reference.pointer, _id_getMask as jni.JMethodIDPtr).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);

  static final _class =
      jni.JClass.forName(r"com/fasterxml/jackson/core/JsonFactory");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonFactoryType();
  static final _id_FORMAT_NAME_JSON = _class.staticFieldId(
    r"FORMAT_NAME_JSON",
    r"Ljava/lang/String;",
  );

  /// 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 =>
      _id_FORMAT_NAME_JSON.get(_class, const jni.JStringType());

  static final _id_DEFAULT_FACTORY_FEATURE_FLAGS = _class.staticFieldId(
    r"DEFAULT_FACTORY_FEATURE_FLAGS",
    r"I",
  );

  /// 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 =>
      _id_DEFAULT_FACTORY_FEATURE_FLAGS.get(_class, const jni.jintType());

  static final _id_DEFAULT_PARSER_FEATURE_FLAGS = _class.staticFieldId(
    r"DEFAULT_PARSER_FEATURE_FLAGS",
    r"I",
  );

  /// 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 =>
      _id_DEFAULT_PARSER_FEATURE_FLAGS.get(_class, const jni.jintType());

  static final _id_DEFAULT_GENERATOR_FEATURE_FLAGS = _class.staticFieldId(
    r"DEFAULT_GENERATOR_FEATURE_FLAGS",
    r"I",
  );

  /// 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 =>
      _id_DEFAULT_GENERATOR_FEATURE_FLAGS.get(_class, const jni.jintType());

  static final _id_DEFAULT_ROOT_VALUE_SEPARATOR = _class.staticFieldId(
    r"DEFAULT_ROOT_VALUE_SEPARATOR",
    r"Lcom/fasterxml/jackson/core/SerializableString;",
  );

  /// 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 =>
      _id_DEFAULT_ROOT_VALUE_SEPARATOR.get(_class, const jni.JObjectType());

  static final _id_new0 = _class.constructorId(
    r"()V",
  );

  static final _new0 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_NewObject")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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(_class.reference.pointer, _id_new0 as jni.JMethodIDPtr)
            .reference);
  }

  static final _id_new1 = _class.constructorId(
    r"(Lcom/fasterxml/jackson/core/ObjectCodec;)V",
  );

  static final _new1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_NewObject")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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(_class.reference.pointer,
            _id_new1 as jni.JMethodIDPtr, oc.reference.pointer)
        .reference);
  }

  static final _id_new2 = _class.constructorId(
    r"(Lcom/fasterxml/jackson/core/JsonFactory;Lcom/fasterxml/jackson/core/ObjectCodec;)V",
  );

  static final _new2 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Pointer<ffi.Void>
                      )>)>>("globalEnv_NewObject")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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(
            _class.reference.pointer,
            _id_new2 as jni.JMethodIDPtr,
            src.reference.pointer,
            codec.reference.pointer)
        .reference);
  }

  static final _id_new3 = _class.constructorId(
    r"(Lcom/fasterxml/jackson/core/JsonFactoryBuilder;)V",
  );

  static final _new3 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_NewObject")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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(_class.reference.pointer,
            _id_new3 as jni.JMethodIDPtr, b.reference.pointer)
        .reference);
  }

  static final _id_new4 = _class.constructorId(
    r"(Lcom/fasterxml/jackson/core/TSFBuilder;Z)V",
  );

  static final _new4 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>, ffi.Int64)>)>>(
          "globalEnv_NewObject")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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(_class.reference.pointer,
            _id_new4 as jni.JMethodIDPtr, b.reference.pointer, bogus ? 1 : 0)
        .reference);
  }

  static final _id_rebuild = _class.instanceMethodId(
    r"rebuild",
    r"()Lcom/fasterxml/jackson/core/TSFBuilder;",
  );

  static final _rebuild = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_rebuild as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_builder = _class.staticMethodId(
    r"builder",
    r"()Lcom/fasterxml/jackson/core/TSFBuilder;",
  );

  static final _builder = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallStaticObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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(_class.reference.pointer, _id_builder as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_copy = _class.instanceMethodId(
    r"copy",
    r"()Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _copy = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_copy as jni.JMethodIDPtr)
        .object(const $JsonFactoryType());
  }

  static final _id_readResolve = _class.instanceMethodId(
    r"readResolve",
    r"()Ljava/lang/Object;",
  );

  static final _readResolve = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_readResolve as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_requiresPropertyOrdering = _class.instanceMethodId(
    r"requiresPropertyOrdering",
    r"()Z",
  );

  static final _requiresPropertyOrdering = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_requiresPropertyOrdering as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_canHandleBinaryNatively = _class.instanceMethodId(
    r"canHandleBinaryNatively",
    r"()Z",
  );

  static final _canHandleBinaryNatively = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_canHandleBinaryNatively as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_canUseCharArrays = _class.instanceMethodId(
    r"canUseCharArrays",
    r"()Z",
  );

  static final _canUseCharArrays = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_canUseCharArrays as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_canParseAsync = _class.instanceMethodId(
    r"canParseAsync",
    r"()Z",
  );

  static final _canParseAsync = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_canParseAsync as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_getFormatReadFeatureType = _class.instanceMethodId(
    r"getFormatReadFeatureType",
    r"()Ljava/lang/Class;",
  );

  static final _getFormatReadFeatureType = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getFormatReadFeatureType as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_getFormatWriteFeatureType = _class.instanceMethodId(
    r"getFormatWriteFeatureType",
    r"()Ljava/lang/Class;",
  );

  static final _getFormatWriteFeatureType = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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,
            _id_getFormatWriteFeatureType as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_canUseSchema = _class.instanceMethodId(
    r"canUseSchema",
    r"(Lcom/fasterxml/jackson/core/FormatSchema;)Z",
  );

  static final _canUseSchema = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_canUseSchema as jni.JMethodIDPtr, schema.reference.pointer)
        .boolean;
  }

  static final _id_getFormatName = _class.instanceMethodId(
    r"getFormatName",
    r"()Ljava/lang/String;",
  );

  static final _getFormatName = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getFormatName as jni.JMethodIDPtr)
        .object(const jni.JStringType());
  }

  static final _id_hasFormat = _class.instanceMethodId(
    r"hasFormat",
    r"(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;",
  );

  static final _hasFormat = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_hasFormat as jni.JMethodIDPtr,
            acc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_requiresCustomCodec = _class.instanceMethodId(
    r"requiresCustomCodec",
    r"()Z",
  );

  static final _requiresCustomCodec = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_requiresCustomCodec as jni.JMethodIDPtr)
        .boolean;
  }

  static final _id_hasJSONFormat = _class.instanceMethodId(
    r"hasJSONFormat",
    r"(Lcom/fasterxml/jackson/core/format/InputAccessor;)Lcom/fasterxml/jackson/core/format/MatchStrength;",
  );

  static final _hasJSONFormat = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_hasJSONFormat as jni.JMethodIDPtr, acc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_version = _class.instanceMethodId(
    r"version",
    r"()Lcom/fasterxml/jackson/core/Version;",
  );

  static final _version = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_version as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_configure = _class.instanceMethodId(
    r"configure",
    r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _configure = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>, ffi.Int64)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_configure as jni.JMethodIDPtr,
            f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _id_enable = _class.instanceMethodId(
    r"enable",
    r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _enable = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_enable as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_disable = _class.instanceMethodId(
    r"disable",
    r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _disable = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_disable as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_isEnabled = _class.instanceMethodId(
    r"isEnabled",
    r"(Lcom/fasterxml/jackson/core/JsonFactory$Feature;)Z",
  );

  static final _isEnabled = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_isEnabled as jni.JMethodIDPtr,
            f.reference.pointer)
        .boolean;
  }

  static final _id_getParserFeatures = _class.instanceMethodId(
    r"getParserFeatures",
    r"()I",
  );

  static final _getParserFeatures = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public final int getParserFeatures()
  int getParserFeatures() {
    return _getParserFeatures(
            reference.pointer, _id_getParserFeatures as jni.JMethodIDPtr)
        .integer;
  }

  static final _id_getGeneratorFeatures = _class.instanceMethodId(
    r"getGeneratorFeatures",
    r"()I",
  );

  static final _getGeneratorFeatures = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public final int getGeneratorFeatures()
  int getGeneratorFeatures() {
    return _getGeneratorFeatures(
            reference.pointer, _id_getGeneratorFeatures as jni.JMethodIDPtr)
        .integer;
  }

  static final _id_getFormatParserFeatures = _class.instanceMethodId(
    r"getFormatParserFeatures",
    r"()I",
  );

  static final _getFormatParserFeatures = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public int getFormatParserFeatures()
  int getFormatParserFeatures() {
    return _getFormatParserFeatures(
            reference.pointer, _id_getFormatParserFeatures as jni.JMethodIDPtr)
        .integer;
  }

  static final _id_getFormatGeneratorFeatures = _class.instanceMethodId(
    r"getFormatGeneratorFeatures",
    r"()I",
  );

  static final _getFormatGeneratorFeatures = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallIntMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// from: public int getFormatGeneratorFeatures()
  int getFormatGeneratorFeatures() {
    return _getFormatGeneratorFeatures(reference.pointer,
            _id_getFormatGeneratorFeatures as jni.JMethodIDPtr)
        .integer;
  }

  static final _id_configure1 = _class.instanceMethodId(
    r"configure",
    r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _configure1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>, ffi.Int64)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_configure1 as jni.JMethodIDPtr,
            f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _id_enable1 = _class.instanceMethodId(
    r"enable",
    r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _enable1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_enable1 as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_disable1 = _class.instanceMethodId(
    r"disable",
    r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _disable1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_disable1 as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_isEnabled1 = _class.instanceMethodId(
    r"isEnabled",
    r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z",
  );

  static final _isEnabled1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_isEnabled1 as jni.JMethodIDPtr,
            f.reference.pointer)
        .boolean;
  }

  static final _id_isEnabled2 = _class.instanceMethodId(
    r"isEnabled",
    r"(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z",
  );

  static final _isEnabled2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_isEnabled2 as jni.JMethodIDPtr,
            f.reference.pointer)
        .boolean;
  }

  static final _id_getInputDecorator = _class.instanceMethodId(
    r"getInputDecorator",
    r"()Lcom/fasterxml/jackson/core/io/InputDecorator;",
  );

  static final _getInputDecorator = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getInputDecorator as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_setInputDecorator = _class.instanceMethodId(
    r"setInputDecorator",
    r"(Lcom/fasterxml/jackson/core/io/InputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _setInputDecorator = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_setInputDecorator as jni.JMethodIDPtr, d.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_configure2 = _class.instanceMethodId(
    r"configure",
    r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;Z)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _configure2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>, ffi.Int64)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_configure2 as jni.JMethodIDPtr,
            f.reference.pointer, state ? 1 : 0)
        .object(const $JsonFactoryType());
  }

  static final _id_enable2 = _class.instanceMethodId(
    r"enable",
    r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _enable2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_enable2 as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_disable2 = _class.instanceMethodId(
    r"disable",
    r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _disable2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_disable2 as jni.JMethodIDPtr,
            f.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_isEnabled3 = _class.instanceMethodId(
    r"isEnabled",
    r"(Lcom/fasterxml/jackson/core/JsonGenerator$Feature;)Z",
  );

  static final _isEnabled3 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_isEnabled3 as jni.JMethodIDPtr,
            f.reference.pointer)
        .boolean;
  }

  static final _id_isEnabled4 = _class.instanceMethodId(
    r"isEnabled",
    r"(Lcom/fasterxml/jackson/core/StreamWriteFeature;)Z",
  );

  static final _isEnabled4 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallBooleanMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_isEnabled4 as jni.JMethodIDPtr,
            f.reference.pointer)
        .boolean;
  }

  static final _id_getCharacterEscapes = _class.instanceMethodId(
    r"getCharacterEscapes",
    r"()Lcom/fasterxml/jackson/core/io/CharacterEscapes;",
  );

  static final _getCharacterEscapes = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getCharacterEscapes as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_setCharacterEscapes = _class.instanceMethodId(
    r"setCharacterEscapes",
    r"(Lcom/fasterxml/jackson/core/io/CharacterEscapes;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _setCharacterEscapes = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_setCharacterEscapes as jni.JMethodIDPtr, esc.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_getOutputDecorator = _class.instanceMethodId(
    r"getOutputDecorator",
    r"()Lcom/fasterxml/jackson/core/io/OutputDecorator;",
  );

  static final _getOutputDecorator = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getOutputDecorator as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_setOutputDecorator = _class.instanceMethodId(
    r"setOutputDecorator",
    r"(Lcom/fasterxml/jackson/core/io/OutputDecorator;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _setOutputDecorator = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_setOutputDecorator as jni.JMethodIDPtr, d.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_setRootValueSeparator = _class.instanceMethodId(
    r"setRootValueSeparator",
    r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _setRootValueSeparator = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_setRootValueSeparator as jni.JMethodIDPtr,
            sep.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_getRootValueSeparator = _class.instanceMethodId(
    r"getRootValueSeparator",
    r"()Ljava/lang/String;",
  );

  static final _getRootValueSeparator = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getRootValueSeparator as jni.JMethodIDPtr)
        .object(const jni.JStringType());
  }

  static final _id_setCodec = _class.instanceMethodId(
    r"setCodec",
    r"(Lcom/fasterxml/jackson/core/ObjectCodec;)Lcom/fasterxml/jackson/core/JsonFactory;",
  );

  static final _setCodec = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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, _id_setCodec as jni.JMethodIDPtr,
            oc.reference.pointer)
        .object(const $JsonFactoryType());
  }

  static final _id_getCodec = _class.instanceMethodId(
    r"getCodec",
    r"()Lcom/fasterxml/jackson/core/ObjectCodec;",
  );

  static final _getCodec = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(
            ffi.Pointer<ffi.Void>,
            jni.JMethodIDPtr,
          )>();

  /// 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, _id_getCodec as jni.JMethodIDPtr)
        .object(const jni.JObjectType());
  }

  static final _id_createParser = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser as jni.JMethodIDPtr, f.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser1 = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser1 as jni.JMethodIDPtr, url.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser2 = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser2 as jni.JMethodIDPtr, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser3 = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser3 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser3 as jni.JMethodIDPtr, r.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser4 = _class.instanceMethodId(
    r"createParser",
    r"([B)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser4 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser4 as jni.JMethodIDPtr, data.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser5 = _class.instanceMethodId(
    r"createParser",
    r"([BII)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser5 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Int64,
                        ffi.Int64
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser5 as jni.JMethodIDPtr,
            data.reference.pointer,
            offset,
            len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser6 = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser6 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser6 as jni.JMethodIDPtr, content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser7 = _class.instanceMethodId(
    r"createParser",
    r"([C)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser7 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser7 as jni.JMethodIDPtr, content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser8 = _class.instanceMethodId(
    r"createParser",
    r"([CII)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser8 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Int64,
                        ffi.Int64
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser8 as jni.JMethodIDPtr,
            content.reference.pointer,
            offset,
            len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createParser9 = _class.instanceMethodId(
    r"createParser",
    r"(Ljava/io/DataInput;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createParser9 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createParser9 as jni.JMethodIDPtr, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createNonBlockingByteArrayParser = _class.instanceMethodId(
    r"createNonBlockingByteArrayParser",
    r"()Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createNonBlockingByteArrayParser =
      ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                    ffi.Pointer<ffi.Void>,
                    jni.JMethodIDPtr,
                  )>>("globalEnv_CallObjectMethod")
          .asFunction<
              jni.JniResult Function(
                ffi.Pointer<ffi.Void>,
                jni.JMethodIDPtr,
              )>();

  /// 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,
            _id_createNonBlockingByteArrayParser as jni.JMethodIDPtr)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createGenerator = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Pointer<ffi.Void>
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator as jni.JMethodIDPtr,
            out.reference.pointer,
            enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createGenerator1 = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator1 as jni.JMethodIDPtr, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createGenerator2 = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator2 as jni.JMethodIDPtr, w.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createGenerator3 = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/File;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator3 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Pointer<ffi.Void>
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator3 as jni.JMethodIDPtr,
            f.reference.pointer,
            enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createGenerator4 = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/DataOutput;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator4 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Pointer<ffi.Void>
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator4 as jni.JMethodIDPtr,
            out.reference.pointer,
            enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createGenerator5 = _class.instanceMethodId(
    r"createGenerator",
    r"(Ljava/io/DataOutput;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createGenerator5 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createGenerator5 as jni.JMethodIDPtr, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createJsonParser = _class.instanceMethodId(
    r"createJsonParser",
    r"(Ljava/io/File;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser as jni.JMethodIDPtr, f.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser1 = _class.instanceMethodId(
    r"createJsonParser",
    r"(Ljava/net/URL;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser1 as jni.JMethodIDPtr, url.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser2 = _class.instanceMethodId(
    r"createJsonParser",
    r"(Ljava/io/InputStream;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser2 as jni.JMethodIDPtr, in0.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser3 = _class.instanceMethodId(
    r"createJsonParser",
    r"(Ljava/io/Reader;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser3 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser3 as jni.JMethodIDPtr, r.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser4 = _class.instanceMethodId(
    r"createJsonParser",
    r"([B)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser4 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser4 as jni.JMethodIDPtr, data.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser5 = _class.instanceMethodId(
    r"createJsonParser",
    r"([BII)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser5 = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Int64,
                        ffi.Int64
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser5 as jni.JMethodIDPtr,
            data.reference.pointer,
            offset,
            len)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonParser6 = _class.instanceMethodId(
    r"createJsonParser",
    r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser;",
  );

  static final _createJsonParser6 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonParser6 as jni.JMethodIDPtr,
            content.reference.pointer)
        .object(const jsonparser_.$JsonParserType());
  }

  static final _id_createJsonGenerator = _class.instanceMethodId(
    r"createJsonGenerator",
    r"(Ljava/io/OutputStream;Lcom/fasterxml/jackson/core/JsonEncoding;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createJsonGenerator = ProtectedJniExtensions.lookup<
          ffi.NativeFunction<
              jni.JniResult Function(
                  ffi.Pointer<ffi.Void>,
                  jni.JMethodIDPtr,
                  ffi.VarArgs<
                      (
                        ffi.Pointer<ffi.Void>,
                        ffi.Pointer<ffi.Void>
                      )>)>>("globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonGenerator as jni.JMethodIDPtr,
            out.reference.pointer,
            enc.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createJsonGenerator1 = _class.instanceMethodId(
    r"createJsonGenerator",
    r"(Ljava/io/Writer;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createJsonGenerator1 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonGenerator1 as jni.JMethodIDPtr, out.reference.pointer)
        .object(const jni.JObjectType());
  }

  static final _id_createJsonGenerator2 = _class.instanceMethodId(
    r"createJsonGenerator",
    r"(Ljava/io/OutputStream;)Lcom/fasterxml/jackson/core/JsonGenerator;",
  );

  static final _createJsonGenerator2 = ProtectedJniExtensions.lookup<
              ffi.NativeFunction<
                  jni.JniResult Function(
                      ffi.Pointer<ffi.Void>,
                      jni.JMethodIDPtr,
                      ffi.VarArgs<(ffi.Pointer<ffi.Void>,)>)>>(
          "globalEnv_CallObjectMethod")
      .asFunction<
          jni.JniResult Function(ffi.Pointer<ffi.Void>, jni.JMethodIDPtr,
              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,
            _id_createJsonGenerator2 as jni.JMethodIDPtr, 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;
  }
}
