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

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 "JsonToken.dart" as jsontoken_;

/// from: com.fasterxml.jackson.core.JsonParser$Feature
///
/// Enumeration that defines all on/off features for parsers.
class JsonParser_Feature extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser_Feature> $type = type;

  JsonParser_Feature.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  static final _class =
      jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser$Feature");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParser_FeatureType();
  static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"values",
      r"()[Lcom/fasterxml/jackson/core/JsonParser$Feature;");

  /// from: static public com.fasterxml.jackson.core.JsonParser.Feature[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonParser_Feature> values() {
    return const jni.JArrayType($JsonParser_FeatureType()).fromRef(
        jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
            _id_values, jni.JniCallType.objectType, []).object);
  }

  static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"valueOf",
      r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$Feature;");

  /// from: static public com.fasterxml.jackson.core.JsonParser.Feature valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonParser_Feature valueOf(
    jni.JString name,
  ) {
    return const $JsonParser_FeatureType().fromRef(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_valueOf,
            jni.JniCallType.objectType, [name.reference.pointer]).object);
  }

  static final _id_collectDefaults = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer, r"collectDefaults", r"()I");

  /// from: static public int collectDefaults()
  ///
  /// Method that calculates bit set (flags) of all features that
  /// are enabled by default.
  ///@return Bit mask of all features that are enabled by default
  static int collectDefaults() {
    return jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
        _id_collectDefaults, jni.JniCallType.intType, []).integer;
  }

  static final _id_enabledByDefault = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"enabledByDefault", r"()Z");

  /// from: public boolean enabledByDefault()
  bool enabledByDefault() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_enabledByDefault, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_enabledIn = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"enabledIn", r"(I)Z");

  /// from: public boolean enabledIn(int flags)
  bool enabledIn(
    int flags,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_enabledIn,
        jni.JniCallType.booleanType,
        [jni.JValueInt(flags)]).boolean;
  }

  static final _id_getMask = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getMask", r"()I");

  /// from: public int getMask()
  int getMask() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getMask, jni.JniCallType.intType, []).integer;
  }
}

final class $JsonParser_FeatureType extends jni.JObjType<JsonParser_Feature> {
  const $JsonParser_FeatureType();

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

  @override
  JsonParser_Feature fromRef(jni.JObjectPtr ref) =>
      JsonParser_Feature.fromRef(ref);

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

  @override
  final superCount = 1;

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

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

/// from: com.fasterxml.jackson.core.JsonParser$NumberType
///
/// Enumeration of possible "native" (optimal) types that can be
/// used for numbers.
class JsonParser_NumberType extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser_NumberType> $type = type;

  JsonParser_NumberType.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  static final _class =
      jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser$NumberType");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParser_NumberTypeType();
  static final _id_values = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"values",
      r"()[Lcom/fasterxml/jackson/core/JsonParser$NumberType;");

  /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType[] values()
  /// The returned object must be released after use, by calling the [release] method.
  static jni.JArray<JsonParser_NumberType> values() {
    return const jni.JArrayType($JsonParser_NumberTypeType()).fromRef(
        jni.Jni.accessors.callStaticMethodWithArgs(_class.reference.pointer,
            _id_values, jni.JniCallType.objectType, []).object);
  }

  static final _id_valueOf = jni.Jni.accessors.getStaticMethodIDOf(
      _class.reference.pointer,
      r"valueOf",
      r"(Ljava/lang/String;)Lcom/fasterxml/jackson/core/JsonParser$NumberType;");

  /// from: static public com.fasterxml.jackson.core.JsonParser.NumberType valueOf(java.lang.String name)
  /// The returned object must be released after use, by calling the [release] method.
  static JsonParser_NumberType valueOf(
    jni.JString name,
  ) {
    return const $JsonParser_NumberTypeType().fromRef(jni.Jni.accessors
        .callStaticMethodWithArgs(_class.reference.pointer, _id_valueOf,
            jni.JniCallType.objectType, [name.reference.pointer]).object);
  }
}

final class $JsonParser_NumberTypeType
    extends jni.JObjType<JsonParser_NumberType> {
  const $JsonParser_NumberTypeType();

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

  @override
  JsonParser_NumberType fromRef(jni.JObjectPtr ref) =>
      JsonParser_NumberType.fromRef(ref);

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

  @override
  final superCount = 1;

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

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

/// from: com.fasterxml.jackson.core.JsonParser
///
/// Base class that defines public API for reading JSON content.
/// Instances are created using factory methods of
/// a JsonFactory instance.
///@author Tatu Saloranta
class JsonParser extends jni.JObject {
  @override
  late final jni.JObjType<JsonParser> $type = type;

  JsonParser.fromRef(
    jni.JObjectPtr ref,
  ) : super.fromRef(ref);

  static final _class =
      jni.Jni.findJClass(r"com/fasterxml/jackson/core/JsonParser");

  /// The type which includes information such as the signature of this class.
  static const type = $JsonParserType();
  static final _id_DEFAULT_READ_CAPABILITIES =
      jni.Jni.accessors.getStaticFieldIDOf(
    _class.reference.pointer,
    r"DEFAULT_READ_CAPABILITIES",
    r"Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;",
  );

  /// from: static protected final com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> DEFAULT_READ_CAPABILITIES
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Default set of StreamReadCapabilityies that may be used as
  /// basis for format-specific readers (or as bogus instance if non-null
  /// set needs to be passed).
  ///@since 2.12
  static jni.JObject get DEFAULT_READ_CAPABILITIES =>
      const jni.JObjectType().fromRef(jni.Jni.accessors
          .getStaticField(_class.reference.pointer,
              _id_DEFAULT_READ_CAPABILITIES, jni.JniCallType.objectType)
          .object);

  static final _id_new0 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"()V");

  /// from: protected void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonParser() {
    return JsonParser.fromRef(jni.Jni.accessors
        .newObjectWithArgs(_class.reference.pointer, _id_new0, []).object);
  }

  static final _id_new1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"<init>", r"(I)V");

  /// from: protected void <init>(int features)
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonParser.new1(
    int features,
  ) {
    return JsonParser.fromRef(jni.Jni.accessors.newObjectWithArgs(
        _class.reference.pointer, _id_new1, [jni.JValueInt(features)]).object);
  }

  static final _id_getCodec = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getCodec",
      r"()Lcom/fasterxml/jackson/core/ObjectCodec;");

  /// from: public abstract com.fasterxml.jackson.core.ObjectCodec getCodec()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for ObjectCodec associated with this
  /// parser, if any. Codec is used by \#readValueAs(Class)
  /// method (and its variants).
  ///@return Codec assigned to this parser, if any; {@code null} if none
  jni.JObject getCodec() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getCodec,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_setCodec = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setCodec",
      r"(Lcom/fasterxml/jackson/core/ObjectCodec;)V");

  /// from: public abstract void setCodec(com.fasterxml.jackson.core.ObjectCodec oc)
  ///
  /// Setter that allows defining ObjectCodec associated with this
  /// parser, if any. Codec is used by \#readValueAs(Class)
  /// method (and its variants).
  ///@param oc Codec to assign, if any; {@code null} if none
  void setCodec(
    jni.JObject oc,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_setCodec,
        jni.JniCallType.voidType, [oc.reference.pointer]).check();
  }

  static final _id_getInputSource = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getInputSource", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object getInputSource()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to get access to object that is used
  /// to access input being parsed; this is usually either
  /// InputStream or Reader, depending on what
  /// parser was constructed with.
  /// Note that returned value may be null in some cases; including
  /// case where parser implementation does not want to exposed raw
  /// source to caller.
  /// In cases where input has been decorated, object returned here
  /// is the decorated version; this allows some level of interaction
  /// between users of parser and decorator object.
  ///
  /// In general use of this accessor should be considered as
  /// "last effort", i.e. only used if no other mechanism is applicable.
  ///@return Input source this parser was configured with
  jni.JObject getInputSource() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getInputSource,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_setRequestPayloadOnError = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setRequestPayloadOnError",
      r"(Lcom/fasterxml/jackson/core/util/RequestPayload;)V");

  /// from: public void setRequestPayloadOnError(com.fasterxml.jackson.core.util.RequestPayload payload)
  ///
  /// Sets the payload to be passed if JsonParseException is thrown.
  ///@param payload Payload to pass
  ///@since 2.8
  void setRequestPayloadOnError(
    jni.JObject payload,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setRequestPayloadOnError,
        jni.JniCallType.voidType,
        [payload.reference.pointer]).check();
  }

  static final _id_setRequestPayloadOnError1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setRequestPayloadOnError",
      r"([BLjava/lang/String;)V");

  /// from: public void setRequestPayloadOnError(byte[] payload, java.lang.String charset)
  ///
  /// Sets the byte[] request payload and the charset
  ///@param payload Payload to pass
  ///@param charset Character encoding for (lazily) decoding payload
  ///@since 2.8
  void setRequestPayloadOnError1(
    jni.JArray<jni.jbyte> payload,
    jni.JString charset,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setRequestPayloadOnError1,
        jni.JniCallType.voidType,
        [payload.reference.pointer, charset.reference.pointer]).check();
  }

  static final _id_setRequestPayloadOnError2 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setRequestPayloadOnError",
      r"(Ljava/lang/String;)V");

  /// from: public void setRequestPayloadOnError(java.lang.String payload)
  ///
  /// Sets the String request payload
  ///@param payload Payload to pass
  ///@since 2.8
  void setRequestPayloadOnError2(
    jni.JString payload,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setRequestPayloadOnError2,
        jni.JniCallType.voidType,
        [payload.reference.pointer]).check();
  }

  static final _id_setSchema = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setSchema",
      r"(Lcom/fasterxml/jackson/core/FormatSchema;)V");

  /// from: public void setSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method to call to make this parser use specified schema. Method must
  /// be called before trying to parse any content, right after parser instance
  /// has been created.
  /// Note that not all parsers support schemas; and those that do usually only
  /// accept specific types of schemas: ones defined for data format parser can read.
  ///
  /// If parser does not support specified schema, UnsupportedOperationException
  /// is thrown.
  ///@param schema Schema to use
  ///@throws UnsupportedOperationException if parser does not support schema
  void setSchema(
    jni.JObject schema,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setSchema,
        jni.JniCallType.voidType,
        [schema.reference.pointer]).check();
  }

  static final _id_getSchema = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getSchema",
      r"()Lcom/fasterxml/jackson/core/FormatSchema;");

  /// from: public com.fasterxml.jackson.core.FormatSchema getSchema()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for accessing Schema that this parser uses, if any.
  /// Default implementation returns null.
  ///@return Schema in use by this parser, if any; {@code null} if none
  ///@since 2.1
  jni.JObject getSchema() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getSchema,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_canUseSchema = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"canUseSchema",
      r"(Lcom/fasterxml/jackson/core/FormatSchema;)Z");

  /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method that can be used to verify that given schema can be used with
  /// this parser (using \#setSchema).
  ///@param schema Schema to check
  ///@return True if this parser can use given schema; false if not
  bool canUseSchema(
    jni.JObject schema,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_canUseSchema,
        jni.JniCallType.booleanType,
        [schema.reference.pointer]).boolean;
  }

  static final _id_requiresCustomCodec = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"requiresCustomCodec", r"()Z");

  /// 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 format-specific codec is needed with this parser; false if a general
  ///   ObjectCodec is enough
  ///@since 2.1
  bool requiresCustomCodec() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_requiresCustomCodec, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_canParseAsync = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"canParseAsync", r"()Z");

  /// from: public boolean canParseAsync()
  ///
  /// Method that can be called to determine if this parser instance
  /// uses non-blocking ("asynchronous") input access for decoding or not.
  /// Access mode is determined by earlier calls via JsonFactory;
  /// it may not be changed after construction.
  ///
  /// If non-blocking decoding is (@code true}, it is possible to call
  /// \#getNonBlockingInputFeeder() to obtain object to use
  /// for feeding input; otherwise (<code>false</code> returned)
  /// input is read by blocking
  ///@return True if this is a non-blocking ("asynchronous") parser
  ///@since 2.9
  bool canParseAsync() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_canParseAsync, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getNonBlockingInputFeeder = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getNonBlockingInputFeeder",
      r"()Lcom/fasterxml/jackson/core/async/NonBlockingInputFeeder;");

  /// from: public com.fasterxml.jackson.core.async.NonBlockingInputFeeder getNonBlockingInputFeeder()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will either return a feeder instance (if parser uses
  /// non-blocking, aka asynchronous access); or <code>null</code> for
  /// parsers that use blocking I/O.
  ///@return Input feeder to use with non-blocking (async) parsing
  ///@since 2.9
  jni.JObject getNonBlockingInputFeeder() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getNonBlockingInputFeeder,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getReadCapabilities = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getReadCapabilities",
      r"()Lcom/fasterxml/jackson/core/util/JacksonFeatureSet;");

  /// from: public com.fasterxml.jackson.core.util.JacksonFeatureSet<com.fasterxml.jackson.core.StreamReadCapability> getReadCapabilities()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for getting metadata on capabilities of this parser, based on
  /// underlying data format being read (directly or indirectly).
  ///@return Set of read capabilities for content to read via this parser
  ///@since 2.12
  jni.JObject getReadCapabilities() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getReadCapabilities,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_version = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"version",
      r"()Lcom/fasterxml/jackson/core/Version;");

  /// from: public abstract com.fasterxml.jackson.core.Version version()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor for getting version of the core package, given a parser instance.
  /// Left for sub-classes to implement.
  ///@return Version of this generator (derived from version declared for
  ///   {@code jackson-core} jar that contains the class
  jni.JObject version() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_version, jni.JniCallType.objectType, []).object);
  }

  static final _id_close = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"close", r"()V");

  /// from: public abstract void close()
  ///
  /// Closes the parser so that no further iteration or data access
  /// can be made; will also close the underlying input source
  /// if parser either __owns__ the input source, or feature
  /// Feature\#AUTO_CLOSE_SOURCE is enabled.
  /// Whether parser owns the input source depends on factory
  /// method that was used to construct instance (so check
  /// com.fasterxml.jackson.core.JsonFactory for details,
  /// but the general
  /// idea is that if caller passes in closable resource (such
  /// as InputStream or Reader) parser does NOT
  /// own the source; but if it passes a reference (such as
  /// java.io.File or java.net.URL and creates
  /// stream or reader it does own them.
  ///@throws IOException if there is either an underlying I/O problem
  void close() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_close, jni.JniCallType.voidType, []).check();
  }

  static final _id_isClosed = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"isClosed", r"()Z");

  /// from: public abstract boolean isClosed()
  ///
  /// Method that can be called to determine whether this parser
  /// is closed or not. If it is closed, no new tokens can be
  /// retrieved by calling \#nextToken (and the underlying
  /// stream may be closed). Closing may be due to an explicit
  /// call to \#close or because parser has encountered
  /// end of input.
  ///@return {@code True} if this parser instance has been closed
  bool isClosed() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_isClosed,
        jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getParsingContext = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getParsingContext",
      r"()Lcom/fasterxml/jackson/core/JsonStreamContext;");

  /// from: public abstract com.fasterxml.jackson.core.JsonStreamContext getParsingContext()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to access current parsing context reader
  /// is in. There are 3 different types: root, array and object contexts,
  /// with slightly different available information. Contexts are
  /// hierarchically nested, and can be used for example for figuring
  /// out part of the input document that correspond to specific
  /// array or object (for highlighting purposes, or error reporting).
  /// Contexts can also be used for simple xpath-like matching of
  /// input, if so desired.
  ///@return Stream input context (JsonStreamContext) associated with this parser
  jni.JObject getParsingContext() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getParsingContext,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_currentLocation = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"currentLocation",
      r"()Lcom/fasterxml/jackson/core/JsonLocation;");

  /// from: public com.fasterxml.jackson.core.JsonLocation currentLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that returns location of the last processed input unit (character
  /// or byte) from the input;
  /// usually for error reporting purposes.
  ///
  /// Note that the location is not guaranteed to be accurate (although most
  /// implementation will try their best): some implementations may only
  /// report specific boundary locations (start or end locations of tokens)
  /// and others only return JsonLocation\#NA due to not having access
  /// to input location information (when delegating actual decoding work
  /// to other library)
  ///@return Location of the last processed input unit (byte or character)
  ///@since 2.13
  jni.JObject currentLocation() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_currentLocation,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_currentTokenLocation = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"currentTokenLocation",
      r"()Lcom/fasterxml/jackson/core/JsonLocation;");

  /// from: public com.fasterxml.jackson.core.JsonLocation currentTokenLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that return the __starting__ location of the current
  /// (most recently returned)
  /// token; that is, the position of the first input unit (character or byte) from input
  /// that starts the current token.
  ///
  /// Note that the location is not guaranteed to be accurate (although most
  /// implementation will try their best): some implementations may only
  /// return JsonLocation\#NA due to not having access
  /// to input location information (when delegating actual decoding work
  /// to other library)
  ///@return Starting location of the token parser currently points to
  ///@since 2.13 (will eventually replace \#getTokenLocation)
  jni.JObject currentTokenLocation() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_currentTokenLocation,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getCurrentLocation = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getCurrentLocation",
      r"()Lcom/fasterxml/jackson/core/JsonLocation;");

  /// from: public abstract com.fasterxml.jackson.core.JsonLocation getCurrentLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentLocation(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Location of the last processed input unit (byte or character)
  jni.JObject getCurrentLocation() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getCurrentLocation,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getTokenLocation = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getTokenLocation",
      r"()Lcom/fasterxml/jackson/core/JsonLocation;");

  /// from: public abstract com.fasterxml.jackson.core.JsonLocation getTokenLocation()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentTokenLocation(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Starting location of the token parser currently points to
  jni.JObject getTokenLocation() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getTokenLocation,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_currentValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"currentValue", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object currentValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Helper method, usually equivalent to:
  ///<code>
  ///   getParsingContext().getCurrentValue();
  ///</code>
  ///
  /// Note that "current value" is NOT populated (or used) by Streaming parser;
  /// it is only used by higher-level data-binding functionality.
  /// The reason it is included here is that it can be stored and accessed hierarchically,
  /// and gets passed through data-binding.
  ///@return "Current value" associated with the current input context (state) of this parser
  ///@since 2.13 (added as replacement for older \#getCurrentValue()
  jni.JObject currentValue() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_currentValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_assignCurrentValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"assignCurrentValue",
      r"(Ljava/lang/Object;)V");

  /// from: public void assignCurrentValue(java.lang.Object v)
  ///
  /// Helper method, usually equivalent to:
  ///<code>
  ///   getParsingContext().setCurrentValue(v);
  ///</code>
  ///@param v Current value to assign for the current input context of this parser
  ///@since 2.13 (added as replacement for older \#setCurrentValue
  void assignCurrentValue(
    jni.JObject v,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_assignCurrentValue,
        jni.JniCallType.voidType,
        [v.reference.pointer]).check();
  }

  static final _id_getCurrentValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getCurrentValue", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object getCurrentValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentValue(), to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@return Location of the last processed input unit (byte or character)
  jni.JObject getCurrentValue() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getCurrentValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_setCurrentValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"setCurrentValue", r"(Ljava/lang/Object;)V");

  /// from: public void setCurrentValue(java.lang.Object v)
  ///
  /// Alias for \#assignCurrentValue, to be deprecated in later
  /// Jackson 2.x versions (and removed from Jackson 3.0).
  ///@param v Current value to assign for the current input context of this parser
  void setCurrentValue(
    jni.JObject v,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setCurrentValue,
        jni.JniCallType.voidType,
        [v.reference.pointer]).check();
  }

  static final _id_releaseBuffered = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"releaseBuffered",
      r"(Ljava/io/OutputStream;)I");

  /// from: public int releaseBuffered(java.io.OutputStream out)
  ///
  /// Method that can be called to push back any content that
  /// has been read but not consumed by the parser. This is usually
  /// done after reading all content of interest using parser.
  /// Content is released by writing it to given stream if possible;
  /// if underlying input is byte-based it can released, if not (char-based)
  /// it can not.
  ///@param out OutputStream to which buffered, undecoded content is written to
  ///@return -1 if the underlying content source is not byte based
  ///    (that is, input can not be sent to OutputStream;
  ///    otherwise number of bytes released (0 if there was nothing to release)
  ///@throws IOException if write to stream threw exception
  int releaseBuffered(
    jni.JObject out,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_releaseBuffered,
        jni.JniCallType.intType,
        [out.reference.pointer]).integer;
  }

  static final _id_releaseBuffered1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"releaseBuffered", r"(Ljava/io/Writer;)I");

  /// from: public int releaseBuffered(java.io.Writer w)
  ///
  /// Method that can be called to push back any content that
  /// has been read but not consumed by the parser.
  /// This is usually
  /// done after reading all content of interest using parser.
  /// Content is released by writing it to given writer if possible;
  /// if underlying input is char-based it can released, if not (byte-based)
  /// it can not.
  ///@param w Writer to which buffered but unprocessed content is written to
  ///@return -1 if the underlying content source is not char-based
  ///    (that is, input can not be sent to Writer;
  ///    otherwise number of chars released (0 if there was nothing to release)
  ///@throws IOException if write using Writer threw exception
  int releaseBuffered1(
    jni.JObject w,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_releaseBuffered1,
        jni.JniCallType.intType,
        [w.reference.pointer]).integer;
  }

  static final _id_enable = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"enable",
      r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser 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 Feature for list of features)
  ///@param f Feature to enable
  ///@return This parser, to allow call chaining
  JsonParser enable(
    JsonParser_Feature f,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_enable,
        jni.JniCallType.objectType,
        [f.reference.pointer]).object);
  }

  static final _id_disable = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"disable",
      r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser 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  feature
  /// (check Feature for list of features)
  ///@param f Feature to disable
  ///@return This parser, to allow call chaining
  JsonParser disable(
    JsonParser_Feature f,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_disable,
        jni.JniCallType.objectType,
        [f.reference.pointer]).object);
  }

  static final _id_configure = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"configure",
      r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;Z)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser 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 feature
  /// (check Feature for list of features)
  ///@param f Feature to enable or disable
  ///@param state Whether to enable feature ({@code true}) or disable ({@code false})
  ///@return This parser, to allow call chaining
  JsonParser configure(
    JsonParser_Feature f,
    bool state,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_configure,
        jni.JniCallType.objectType,
        [f.reference.pointer, state ? 1 : 0]).object);
  }

  static final _id_isEnabled = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"isEnabled",
      r"(Lcom/fasterxml/jackson/core/JsonParser$Feature;)Z");

  /// from: public boolean isEnabled(com.fasterxml.jackson.core.JsonParser.Feature f)
  ///
  /// Method for checking whether specified Feature is enabled.
  ///@param f Feature to check
  ///@return {@code True} if feature is enabled; {@code false} otherwise
  bool isEnabled(
    JsonParser_Feature f,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_isEnabled,
        jni.JniCallType.booleanType,
        [f.reference.pointer]).boolean;
  }

  static final _id_isEnabled1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"isEnabled",
      r"(Lcom/fasterxml/jackson/core/StreamReadFeature;)Z");

  /// from: public boolean isEnabled(com.fasterxml.jackson.core.StreamReadFeature f)
  ///
  /// Method for checking whether specified Feature is enabled.
  ///@param f Feature to check
  ///@return {@code True} if feature is enabled; {@code false} otherwise
  ///@since 2.10
  bool isEnabled1(
    jni.JObject f,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_isEnabled1,
        jni.JniCallType.booleanType,
        [f.reference.pointer]).boolean;
  }

  static final _id_getFeatureMask = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getFeatureMask", r"()I");

  /// from: public int getFeatureMask()
  ///
  /// Bulk access method for getting state of all standard Features.
  ///@return Bit mask that defines current states of all standard Features.
  ///@since 2.3
  int getFeatureMask() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getFeatureMask, jni.JniCallType.intType, []).integer;
  }

  static final _id_setFeatureMask = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"setFeatureMask",
      r"(I)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser setFeatureMask(int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of all standard Features
  ///@param mask Bit mask that defines set of features to enable
  ///@return This parser, to allow call chaining
  ///@since 2.3
  ///@deprecated Since 2.7, use \#overrideStdFeatures(int, int) instead
  JsonParser setFeatureMask(
    int mask,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_setFeatureMask,
        jni.JniCallType.objectType,
        [jni.JValueInt(mask)]).object);
  }

  static final _id_overrideStdFeatures = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"overrideStdFeatures",
      r"(II)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser overrideStdFeatures(int values, int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of features specified by <code>mask</code>.
  /// Functionally equivalent to
  ///<code>
  ///    int oldState = getFeatureMask();
  ///    int newState = (oldState &amp; ~mask) | (values &amp; mask);
  ///    setFeatureMask(newState);
  ///</code>
  /// but preferred as this lets caller more efficiently specify actual changes made.
  ///@param values Bit mask of set/clear state for features to change
  ///@param mask Bit mask of features to change
  ///@return This parser, to allow call chaining
  ///@since 2.6
  JsonParser overrideStdFeatures(
    int values,
    int mask,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overrideStdFeatures,
        jni.JniCallType.objectType,
        [jni.JValueInt(values), jni.JValueInt(mask)]).object);
  }

  static final _id_getFormatFeatures = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getFormatFeatures", r"()I");

  /// from: public int getFormatFeatures()
  ///
  /// Bulk access method for getting state of all FormatFeatures, format-specific
  /// on/off configuration settings.
  ///@return Bit mask that defines current states of all standard FormatFeatures.
  ///@since 2.6
  int getFormatFeatures() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getFormatFeatures, jni.JniCallType.intType, []).integer;
  }

  static final _id_overrideFormatFeatures = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"overrideFormatFeatures",
      r"(II)Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public com.fasterxml.jackson.core.JsonParser overrideFormatFeatures(int values, int mask)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Bulk set method for (re)setting states of FormatFeatures,
  /// by specifying values (set / clear) along with a mask, to determine
  /// which features to change, if any.
  ///
  /// Default implementation will simply throw an exception to indicate that
  /// the parser implementation does not support any FormatFeatures.
  ///@param values Bit mask of set/clear state for features to change
  ///@param mask Bit mask of features to change
  ///@return This parser, to allow call chaining
  ///@since 2.6
  JsonParser overrideFormatFeatures(
    int values,
    int mask,
  ) {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overrideFormatFeatures,
        jni.JniCallType.objectType,
        [jni.JValueInt(values), jni.JValueInt(mask)]).object);
  }

  static final _id_nextToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"nextToken",
      r"()Lcom/fasterxml/jackson/core/JsonToken;");

  /// from: public abstract com.fasterxml.jackson.core.JsonToken nextToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Main iteration method, which will advance stream enough
  /// to determine type of the next token, if any. If none
  /// remaining (stream has no content other than possible
  /// white space before ending), null will be returned.
  ///@return Next token from the stream, if any found, or null
  ///   to indicate end-of-input
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jsontoken_.JsonToken nextToken() {
    return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_nextToken,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_nextValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"nextValue",
      r"()Lcom/fasterxml/jackson/core/JsonToken;");

  /// from: public abstract com.fasterxml.jackson.core.JsonToken nextValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Iteration method that will advance stream enough
  /// to determine type of the next token that is a value type
  /// (including JSON Array and Object start/end markers).
  /// Or put another way, nextToken() will be called once,
  /// and if JsonToken\#FIELD_NAME is returned, another
  /// time to get the value for the field.
  /// Method is most useful for iterating over value entries
  /// of JSON objects; field name will still be available
  /// by calling \#getCurrentName when parser points to
  /// the value.
  ///@return Next non-field-name token from the stream, if any found,
  ///   or null to indicate end-of-input (or, for non-blocking
  ///   parsers, JsonToken\#NOT_AVAILABLE if no tokens were
  ///   available yet)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jsontoken_.JsonToken nextValue() {
    return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_nextValue,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_nextFieldName = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"nextFieldName",
      r"(Lcom/fasterxml/jackson/core/SerializableString;)Z");

  /// from: public boolean nextFieldName(com.fasterxml.jackson.core.SerializableString str)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// verifies whether it is JsonToken\#FIELD_NAME with specified name
  /// and returns result of that comparison.
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.FIELD_NAME) &amp;&amp; str.getValue().equals(getCurrentName());
  ///</pre>
  /// but may be faster for parser to verify, and can therefore be used if caller
  /// expects to get such a property name from input next.
  ///@param str Property name to compare next token to (if next token is
  ///   <code>JsonToken.FIELD_NAME</code>)
  ///@return {@code True} if parser advanced to {@code JsonToken.FIELD_NAME} with
  ///    specified name; {@code false} otherwise (different token or non-matching name)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool nextFieldName(
    jni.JObject str,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_nextFieldName,
        jni.JniCallType.booleanType,
        [str.reference.pointer]).boolean;
  }

  static final _id_nextFieldName1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"nextFieldName", r"()Ljava/lang/String;");

  /// from: public java.lang.String nextFieldName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// verifies whether it is JsonToken\#FIELD_NAME; if it is,
  /// returns same as \#getCurrentName(), otherwise null.
  ///@return Name of the the {@code JsonToken.FIELD_NAME} parser advanced to, if any;
  ///   {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.5
  jni.JString nextFieldName1() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_nextFieldName1,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_nextTextValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"nextTextValue", r"()Ljava/lang/String;");

  /// from: public java.lang.String nextTextValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_STRING returns contained String value;
  /// otherwise returns null.
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a String value next from input.
  ///@return Text value of the {@code JsonToken.VALUE_STRING} token parser advanced
  ///   to; or {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString nextTextValue() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_nextTextValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_nextIntValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"nextIntValue", r"(I)I");

  /// from: public int nextIntValue(int defaultValue)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_NUMBER_INT returns 32-bit int value;
  /// otherwise returns specified default value
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get an int value next from input.
  ///
  /// NOTE: value checks are performed similar to \#getIntValue()
  ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
  ///@return Integer ({@code int}) value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
  ///   to; or {@code defaultValue} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@throws InputCoercionException if integer number does not fit in Java {@code int}
  int nextIntValue(
    int defaultValue,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_nextIntValue,
        jni.JniCallType.intType,
        [jni.JValueInt(defaultValue)]).integer;
  }

  static final _id_nextLongValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"nextLongValue", r"(J)J");

  /// from: public long nextLongValue(long defaultValue)
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_NUMBER_INT returns 64-bit long value;
  /// otherwise returns specified default value
  /// It is functionally equivalent to:
  ///<pre>
  ///  return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a long value next from input.
  ///
  /// NOTE: value checks are performed similar to \#getLongValue()
  ///@param defaultValue Value to return if next token is NOT of type {@code JsonToken.VALUE_NUMBER_INT}
  ///@return {@code long} value of the {@code JsonToken.VALUE_NUMBER_INT} token parser advanced
  ///   to; or {@code defaultValue} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@throws InputCoercionException if integer number does not fit in Java {@code long}
  int nextLongValue(
    int defaultValue,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_nextLongValue, jni.JniCallType.longType, [defaultValue]).long;
  }

  static final _id_nextBooleanValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"nextBooleanValue", r"()Ljava/lang/Boolean;");

  /// from: public java.lang.Boolean nextBooleanValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that fetches next token (as if calling \#nextToken) and
  /// if it is JsonToken\#VALUE_TRUE or JsonToken\#VALUE_FALSE
  /// returns matching Boolean value; otherwise return null.
  /// It is functionally equivalent to:
  ///<pre>
  ///  JsonToken t = nextToken();
  ///  if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE;
  ///  if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE;
  ///  return null;
  ///</pre>
  /// but may be faster for parser to process, and can therefore be used if caller
  /// expects to get a Boolean value next from input.
  ///@return {@code Boolean} value of the {@code JsonToken.VALUE_TRUE} or {@code JsonToken.VALUE_FALSE}
  ///   token parser advanced to; or {@code null} if next token is of some other type
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JBoolean nextBooleanValue() {
    return const jni.JBooleanType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_nextBooleanValue,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_skipChildren = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"skipChildren",
      r"()Lcom/fasterxml/jackson/core/JsonParser;");

  /// from: public abstract com.fasterxml.jackson.core.JsonParser skipChildren()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will skip all child tokens of an array or
  /// object token that the parser currently points to,
  /// iff stream points to
  /// JsonToken\#START_OBJECT or JsonToken\#START_ARRAY.
  /// If not, it will do nothing.
  /// After skipping, stream will point to __matching__
  /// JsonToken\#END_OBJECT or JsonToken\#END_ARRAY
  /// (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens
  /// as well as value tokens).
  /// The idea is that after calling this method, application
  /// will call \#nextToken to point to the next
  /// available token, if any.
  ///@return This parser, to allow call chaining
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  JsonParser skipChildren() {
    return const $JsonParserType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_skipChildren,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_finishToken = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"finishToken", r"()V");

  /// from: public void finishToken()
  ///
  /// Method that may be used to force full handling of the current token
  /// so that even if lazy processing is enabled, the whole contents are
  /// read for possible retrieval. This is usually used to ensure that
  /// the token end location is available, as well as token contents
  /// (similar to what calling, say \#getTextCharacters(), would
  /// achieve).
  ///
  /// Note that for many dataformat implementations this method
  /// will not do anything; this is the default implementation unless
  /// overridden by sub-classes.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.8
  void finishToken() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_finishToken, jni.JniCallType.voidType, []).check();
  }

  static final _id_currentToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"currentToken",
      r"()Lcom/fasterxml/jackson/core/JsonToken;");

  /// from: public com.fasterxml.jackson.core.JsonToken currentToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor to find which token parser currently points to, if any;
  /// null will be returned if none.
  /// If return value is non-null, data associated with the token
  /// is available via other accessor methods.
  ///@return Type of the token this parser currently points to,
  ///   if any: null before any tokens have been read, and
  ///   after end-of-input has been encountered, as well as
  ///   if the current token has been explicitly cleared.
  ///@since 2.8
  jsontoken_.JsonToken currentToken() {
    return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_currentToken,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_currentTokenId = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"currentTokenId", r"()I");

  /// from: public int currentTokenId()
  ///
  /// Method similar to \#getCurrentToken() but that returns an
  /// <code>int</code> instead of JsonToken (enum value).
  ///
  /// Use of int directly is typically more efficient on switch statements,
  /// so this method may be useful when building low-overhead codecs.
  /// Note, however, that effect may not be big enough to matter: make sure
  /// to profile performance before deciding to use this method.
  ///@since 2.8
  ///@return {@code int} matching one of constants from JsonTokenId.
  int currentTokenId() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_currentTokenId, jni.JniCallType.intType, []).integer;
  }

  static final _id_getCurrentToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getCurrentToken",
      r"()Lcom/fasterxml/jackson/core/JsonToken;");

  /// from: public abstract com.fasterxml.jackson.core.JsonToken getCurrentToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias for \#currentToken(), may be deprecated sometime after
  /// Jackson 2.13 (will be removed from 3.0).
  ///@return Type of the token this parser currently points to,
  ///   if any: null before any tokens have been read, and
  jsontoken_.JsonToken getCurrentToken() {
    return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getCurrentToken,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_getCurrentTokenId = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getCurrentTokenId", r"()I");

  /// from: public abstract int getCurrentTokenId()
  ///
  /// Deprecated alias for \#currentTokenId().
  ///@return {@code int} matching one of constants from JsonTokenId.
  ///@deprecated Since 2.12 use \#currentTokenId instead
  int getCurrentTokenId() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getCurrentTokenId, jni.JniCallType.intType, []).integer;
  }

  static final _id_hasCurrentToken = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"hasCurrentToken", r"()Z");

  /// from: public abstract boolean hasCurrentToken()
  ///
  /// Method for checking whether parser currently points to
  /// a token (and data for that token is available).
  /// Equivalent to check for <code>parser.getCurrentToken() != null</code>.
  ///@return True if the parser just returned a valid
  ///   token via \#nextToken; false otherwise (parser
  ///   was just constructed, encountered end-of-input
  ///   and returned null from \#nextToken, or the token
  ///   has been consumed)
  bool hasCurrentToken() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_hasCurrentToken, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_hasTokenId = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"hasTokenId", r"(I)Z");

  /// from: public abstract boolean hasTokenId(int id)
  ///
  /// Method that is functionally equivalent to:
  ///<code>
  ///  return currentTokenId() == id
  ///</code>
  /// but may be more efficiently implemented.
  ///
  /// Note that no traversal or conversion is performed; so in some
  /// cases calling method like \#isExpectedStartArrayToken()
  /// is necessary instead.
  ///@param id Token id to match (from (@link JsonTokenId})
  ///@return {@code True} if the parser current points to specified token
  ///@since 2.5
  bool hasTokenId(
    int id,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_hasTokenId,
        jni.JniCallType.booleanType,
        [jni.JValueInt(id)]).boolean;
  }

  static final _id_hasToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"hasToken",
      r"(Lcom/fasterxml/jackson/core/JsonToken;)Z");

  /// from: public abstract boolean hasToken(com.fasterxml.jackson.core.JsonToken t)
  ///
  /// Method that is functionally equivalent to:
  ///<code>
  ///  return currentToken() == t
  ///</code>
  /// but may be more efficiently implemented.
  ///
  /// Note that no traversal or conversion is performed; so in some
  /// cases calling method like \#isExpectedStartArrayToken()
  /// is necessary instead.
  ///@param t Token to match
  ///@return {@code True} if the parser current points to specified token
  ///@since 2.6
  bool hasToken(
    jsontoken_.JsonToken t,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_hasToken,
        jni.JniCallType.booleanType, [t.reference.pointer]).boolean;
  }

  static final _id_isExpectedStartArrayToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"isExpectedStartArrayToken", r"()Z");

  /// from: public boolean isExpectedStartArrayToken()
  ///
  /// Specialized accessor that can be used to verify that the current
  /// token indicates start array (usually meaning that current token
  /// is JsonToken\#START_ARRAY) when start array is expected.
  /// For some specialized parsers this can return true for other cases
  /// as well; this is usually done to emulate arrays in cases underlying
  /// format is ambiguous (XML, for example, has no format-level difference
  /// between Objects and Arrays; it just has elements).
  ///
  /// Default implementation is equivalent to:
  ///<pre>
  ///   currentToken() == JsonToken.START_ARRAY
  ///</pre>
  /// but may be overridden by custom parser implementations.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#START_ARRAY);
  ///   {@code false} if not
  bool isExpectedStartArrayToken() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_isExpectedStartArrayToken, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_isExpectedStartObjectToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"isExpectedStartObjectToken", r"()Z");

  /// from: public boolean isExpectedStartObjectToken()
  ///
  /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
  /// currently points to JsonToken\#START_OBJECT.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#START_OBJECT);
  ///   {@code false} if not
  ///@since 2.5
  bool isExpectedStartObjectToken() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_isExpectedStartObjectToken,
        jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_isExpectedNumberIntToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"isExpectedNumberIntToken", r"()Z");

  /// from: public boolean isExpectedNumberIntToken()
  ///
  /// Similar to \#isExpectedStartArrayToken(), but checks whether stream
  /// currently points to JsonToken\#VALUE_NUMBER_INT.
  ///
  /// The initial use case is for XML backend to efficiently (attempt to) coerce
  /// textual content into numbers.
  ///@return True if the current token can be considered as a
  ///   start-array marker (such JsonToken\#VALUE_NUMBER_INT);
  ///   {@code false} if not
  ///@since 2.12
  bool isExpectedNumberIntToken() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_isExpectedNumberIntToken, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_isNaN = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"isNaN", r"()Z");

  /// from: public boolean isNaN()
  ///
  /// Access for checking whether current token is a numeric value token, but
  /// one that is of "not-a-number" (NaN) variety (including both "NaN" AND
  /// positive/negative infinity!): not supported by all formats,
  /// but often supported for JsonToken\#VALUE_NUMBER_FLOAT.
  /// NOTE: roughly equivalent to calling <code>!Double.isFinite()</code>
  /// on value you would get from calling \#getDoubleValue().
  ///@return {@code True} if the current token is of type JsonToken\#VALUE_NUMBER_FLOAT
  ///   but represents a "Not a Number"; {@code false} for other tokens and regular
  ///   floating-point numbers
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.9
  bool isNaN() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_isNaN, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_clearCurrentToken = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"clearCurrentToken", r"()V");

  /// from: public abstract void clearCurrentToken()
  ///
  /// Method called to "consume" the current token by effectively
  /// removing it so that \#hasCurrentToken returns false, and
  /// \#getCurrentToken null).
  /// Cleared token value can still be accessed by calling
  /// \#getLastClearedToken (if absolutely needed), but
  /// usually isn't.
  ///
  /// Method was added to be used by the optional data binder, since
  /// it has to be able to consume last token used for binding (so that
  /// it will not be used again).
  void clearCurrentToken() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_clearCurrentToken, jni.JniCallType.voidType, []).check();
  }

  static final _id_getLastClearedToken = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getLastClearedToken",
      r"()Lcom/fasterxml/jackson/core/JsonToken;");

  /// from: public abstract com.fasterxml.jackson.core.JsonToken getLastClearedToken()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to get the last token that was
  /// cleared using \#clearCurrentToken. This is not necessarily
  /// the latest token read.
  /// Will return null if no tokens have been cleared,
  /// or if parser has been closed.
  ///@return Last cleared token, if any; {@code null} otherwise
  jsontoken_.JsonToken getLastClearedToken() {
    return const jsontoken_.$JsonTokenType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getLastClearedToken,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_overrideCurrentName = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"overrideCurrentName",
      r"(Ljava/lang/String;)V");

  /// from: public abstract void overrideCurrentName(java.lang.String name)
  ///
  /// Method that can be used to change what is considered to be
  /// the current (field) name.
  /// May be needed to support non-JSON data formats or unusual binding
  /// conventions; not needed for typical processing.
  ///
  /// Note that use of this method should only be done as sort of last
  /// resort, as it is a work-around for regular operation.
  ///@param name Name to use as the current name; may be null.
  void overrideCurrentName(
    jni.JString name,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_overrideCurrentName,
        jni.JniCallType.voidType,
        [name.reference.pointer]).check();
  }

  static final _id_getCurrentName = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getCurrentName", r"()Ljava/lang/String;");

  /// from: public abstract java.lang.String getCurrentName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Alias of \#currentName().
  ///@return Name of the current field in the parsing context
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString getCurrentName() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getCurrentName,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_currentName = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"currentName", r"()Ljava/lang/String;");

  /// from: public java.lang.String currentName()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to get the name associated with
  /// the current token: for JsonToken\#FIELD_NAMEs it will
  /// be the same as what \#getText returns;
  /// for field values it will be preceding field name;
  /// and for others (array values, root-level values) null.
  ///@return Name of the current field in the parsing context
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.10
  jni.JString currentName() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_currentName,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getText = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getText", r"()Ljava/lang/String;");

  /// from: public abstract java.lang.String getText()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for accessing textual representation of the current token;
  /// if no current token (before first call to \#nextToken, or
  /// after encountering end-of-input), returns null.
  /// Method can be called for any token type.
  ///@return Textual value associated with the current token (one returned
  ///   by \#nextToken() or other iteration methods)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JString getText() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getText, jni.JniCallType.objectType, []).object);
  }

  static final _id_getText1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getText", r"(Ljava/io/Writer;)I");

  /// from: public int getText(java.io.Writer writer)
  ///
  /// Method to read the textual representation of the current token in chunks and
  /// pass it to the given Writer.
  /// Conceptually same as calling:
  ///<pre>
  ///  writer.write(parser.getText());
  ///</pre>
  /// but should typically be more efficient as longer content does need to
  /// be combined into a single <code>String</code> to return, and write
  /// can occur directly from intermediate buffers Jackson uses.
  ///@param writer Writer to write textual content to
  ///@return The number of characters written to the Writer
  ///@throws IOException for low-level read issues or writes using passed
  ///   {@code writer}, or
  ///   JsonParseException for decoding problems
  ///@since 2.8
  int getText1(
    jni.JObject writer,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer, _id_getText1,
        jni.JniCallType.intType, [writer.reference.pointer]).integer;
  }

  static final _id_getTextCharacters = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getTextCharacters", r"()[C");

  /// from: public abstract char[] getTextCharacters()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method similar to \#getText, but that will return
  /// underlying (unmodifiable) character array that contains
  /// textual value, instead of constructing a String object
  /// to contain this information.
  /// Note, however, that:
  ///<ul>
  /// <li>Textual contents are not guaranteed to start at
  ///   index 0 (rather, call \#getTextOffset) to
  ///   know the actual offset
  ///  </li>
  /// <li>Length of textual contents may be less than the
  ///  length of returned buffer: call \#getTextLength
  ///  for actual length of returned content.
  ///  </li>
  /// </ul>
  ///
  /// Note that caller __MUST NOT__ modify the returned
  /// character array in any way -- doing so may corrupt
  /// current parser state and render parser instance useless.
  ///
  /// The only reason to call this method (over \#getText)
  /// is to avoid construction of a String object (which
  /// will make a copy of contents).
  ///@return Buffer that contains the current textual value (but not necessarily
  ///    at offset 0, and not necessarily until the end of buffer)
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jchar> getTextCharacters() {
    return const jni.JArrayType(jni.jcharType()).fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getTextCharacters,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_getTextLength = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getTextLength", r"()I");

  /// from: public abstract int getTextLength()
  ///
  /// Accessor used with \#getTextCharacters, to know length
  /// of String stored in returned buffer.
  ///@return Number of characters within buffer returned
  ///   by \#getTextCharacters that are part of
  ///   textual content of the current token.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getTextLength() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getTextLength, jni.JniCallType.intType, []).integer;
  }

  static final _id_getTextOffset = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getTextOffset", r"()I");

  /// from: public abstract int getTextOffset()
  ///
  /// Accessor used with \#getTextCharacters, to know offset
  /// of the first text content character within buffer.
  ///@return Offset of the first character within buffer returned
  ///   by \#getTextCharacters that is part of
  ///   textual content of the current token.
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getTextOffset() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getTextOffset, jni.JniCallType.intType, []).integer;
  }

  static final _id_hasTextCharacters = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"hasTextCharacters", r"()Z");

  /// from: public abstract boolean hasTextCharacters()
  ///
  /// Method that can be used to determine whether calling of
  /// \#getTextCharacters would be the most efficient
  /// way to access textual content for the event parser currently
  /// points to.
  ///
  /// Default implementation simply returns false since only actual
  /// implementation class has knowledge of its internal buffering
  /// state.
  /// Implementations are strongly encouraged to properly override
  /// this method, to allow efficient copying of content by other
  /// code.
  ///@return True if parser currently has character array that can
  ///   be efficiently returned via \#getTextCharacters; false
  ///   means that it may or may not exist
  bool hasTextCharacters() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_hasTextCharacters, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getNumberValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getNumberValue", r"()Ljava/lang/Number;");

  /// from: public abstract java.lang.Number getNumberValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Generic number value accessor method that will work for
  /// all kinds of numeric values. It will return the optimal
  /// (simplest/smallest possible) wrapper object that can
  /// express the numeric value just parsed.
  ///@return Numeric value of the current token in its most optimal
  ///   representation
  ///@throws IOException Problem with access: JsonParseException if
  ///    the current token is not numeric, or if decoding of the value fails
  ///    (invalid format for numbers); plain IOException if underlying
  ///    content read fails (possible if values are extracted lazily)
  jni.JNumber getNumberValue() {
    return const jni.JNumberType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getNumberValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getNumberValueExact = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getNumberValueExact",
      r"()Ljava/lang/Number;");

  /// from: public java.lang.Number getNumberValueExact()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method similar to \#getNumberValue with the difference that
  /// for floating-point numbers value returned may be BigDecimal
  /// if the underlying format does not store floating-point numbers using
  /// native representation: for example, textual formats represent numbers
  /// as Strings (which are 10-based), and conversion to java.lang.Double
  /// is potentially lossy operation.
  ///
  /// Default implementation simply returns \#getNumberValue()
  ///@return Numeric value of the current token using most accurate representation
  ///@throws IOException Problem with access: JsonParseException if
  ///    the current token is not numeric, or if decoding of the value fails
  ///    (invalid format for numbers); plain IOException if underlying
  ///    content read fails (possible if values are extracted lazily)
  ///@since 2.12
  jni.JNumber getNumberValueExact() {
    return const jni.JNumberType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getNumberValueExact,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getNumberType = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getNumberType",
      r"()Lcom/fasterxml/jackson/core/JsonParser$NumberType;");

  /// from: public abstract com.fasterxml.jackson.core.JsonParser.NumberType getNumberType()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// If current token is of type
  /// JsonToken\#VALUE_NUMBER_INT or
  /// JsonToken\#VALUE_NUMBER_FLOAT, returns
  /// one of NumberType constants; otherwise returns null.
  ///@return Type of current number, if parser points to numeric token; {@code null} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  JsonParser_NumberType getNumberType() {
    return const $JsonParser_NumberTypeType().fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getNumberType,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_getByteValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getByteValue", r"()B");

  /// from: public byte getByteValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java byte primitive type.
  /// Note that in addition to "natural" input range of {@code [-128, 127]},
  /// this also allows "unsigned 8-bit byte" values {@code [128, 255]}:
  /// but for this range value will be translated by truncation, leading
  /// to sign change.
  ///
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// {@code [-128, 255]},
  /// a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code byte} (if numeric token within
  ///   range of {@code [-128, 255]}); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getByteValue() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getByteValue, jni.JniCallType.byteType, []).byte;
  }

  static final _id_getShortValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getShortValue", r"()S");

  /// from: public short getShortValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java short primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// Java short, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code short} (if numeric token within
  ///   Java 16-bit signed {@code short} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getShortValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getShortValue, jni.JniCallType.shortType, []).short;
  }

  static final _id_getIntValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getIntValue", r"()I");

  /// from: public abstract int getIntValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a value of Java int primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the resulting integer value falls outside range of
  /// Java {@code int}, a InputCoercionException
  /// may be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code int} (if numeric token within
  ///   Java 32-bit signed {@code int} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getIntValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getIntValue, jni.JniCallType.intType, []).integer;
  }

  static final _id_getLongValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getLongValue", r"()J");

  /// from: public abstract long getLongValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can be expressed as a Java long primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDoubleValue
  /// and then casting to int; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the token is an integer, but its value falls
  /// outside of range of Java long, a InputCoercionException
  /// may be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code long} (if numeric token within
  ///   Java 32-bit signed {@code long} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getLongValue() {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer, _id_getLongValue, jni.JniCallType.longType, []).long;
  }

  static final _id_getBigIntegerValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getBigIntegerValue",
      r"()Ljava/math/BigInteger;");

  /// from: public abstract java.math.BigInteger getBigIntegerValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_INT and
  /// it can not be used as a Java long primitive type due to its
  /// magnitude.
  /// It can also be called for JsonToken\#VALUE_NUMBER_FLOAT;
  /// if so, it is equivalent to calling \#getDecimalValue
  /// and then constructing a BigInteger from that value.
  ///@return Current number value as BigInteger (if numeric token);
  ///     otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getBigIntegerValue() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getBigIntegerValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getFloatValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getFloatValue", r"()F");

  /// from: public abstract float getFloatValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
  /// it can be expressed as a Java float primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
  /// if so, it is equivalent to calling \#getLongValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the value falls
  /// outside of range of Java float, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code float} (if numeric token within
  ///   Java {@code float} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getFloatValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getFloatValue, jni.JniCallType.floatType, []).float;
  }

  static final _id_getDoubleValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getDoubleValue", r"()D");

  /// from: public abstract double getDoubleValue()
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT and
  /// it can be expressed as a Java double primitive type.
  /// It can also be called for JsonToken\#VALUE_NUMBER_INT;
  /// if so, it is equivalent to calling \#getLongValue
  /// and then casting; except for possible overflow/underflow
  /// exception.
  ///
  /// Note: if the value falls
  /// outside of range of Java double, a InputCoercionException
  /// will be thrown to indicate numeric overflow/underflow.
  ///@return Current number value as {@code double} (if numeric token within
  ///   Java {@code double} range); otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getDoubleValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getDoubleValue, jni.JniCallType.doubleType, []).doubleFloat;
  }

  static final _id_getDecimalValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getDecimalValue",
      r"()Ljava/math/BigDecimal;");

  /// from: public abstract java.math.BigDecimal getDecimalValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Numeric accessor that can be called when the current
  /// token is of type JsonToken\#VALUE_NUMBER_FLOAT or
  /// JsonToken\#VALUE_NUMBER_INT. No under/overflow exceptions
  /// are ever thrown.
  ///@return Current number value as BigDecimal (if numeric token);
  ///   otherwise exception thrown
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getDecimalValue() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getDecimalValue,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getBooleanValue = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getBooleanValue", r"()Z");

  /// from: public boolean getBooleanValue()
  ///
  /// Convenience accessor that can be called when the current
  /// token is JsonToken\#VALUE_TRUE or
  /// JsonToken\#VALUE_FALSE, to return matching {@code boolean}
  /// value.
  /// If the current token is of some other type, JsonParseException
  /// will be thrown
  ///@return {@code True} if current token is {@code JsonToken.VALUE_TRUE},
  ///   {@code false} if current token is {@code JsonToken.VALUE_FALSE};
  ///   otherwise throws JsonParseException
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getBooleanValue() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getBooleanValue, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getEmbeddedObject = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getEmbeddedObject", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object getEmbeddedObject()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Accessor that can be called if (and only if) the current token
  /// is JsonToken\#VALUE_EMBEDDED_OBJECT. For other token types,
  /// null is returned.
  ///
  /// Note: only some specialized parser implementations support
  /// embedding of objects (usually ones that are facades on top
  /// of non-streaming sources, such as object trees). One exception
  /// is access to binary content (whether via base64 encoding or not)
  /// which typically is accessible using this method, as well as
  /// \#getBinaryValue().
  ///@return Embedded value (usually of "native" type supported by format)
  ///   for the current token, if any; {@code null otherwise}
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JObject getEmbeddedObject() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getEmbeddedObject,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getBinaryValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getBinaryValue",
      r"(Lcom/fasterxml/jackson/core/Base64Variant;)[B");

  /// from: public abstract byte[] getBinaryValue(com.fasterxml.jackson.core.Base64Variant bv)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be used to read (and consume -- results
  /// may not be accessible using other methods after the call)
  /// base64-encoded binary data
  /// included in the current textual JSON value.
  /// It works similar to getting String value via \#getText
  /// and decoding result (except for decoding part),
  /// but should be significantly more performant.
  ///
  /// Note that non-decoded textual contents of the current token
  /// are not guaranteed to be accessible after this method
  /// is called. Current implementation, for example, clears up
  /// textual content during decoding.
  /// Decoded binary content, however, will be retained until
  /// parser is advanced to the next event.
  ///@param bv Expected variant of base64 encoded
  ///   content (see Base64Variants for definitions
  ///   of "standard" variants).
  ///@return Decoded binary data
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jbyte> getBinaryValue(
    jni.JObject bv,
  ) {
    return const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getBinaryValue,
            jni.JniCallType.objectType, [bv.reference.pointer]).object);
  }

  static final _id_getBinaryValue1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getBinaryValue", r"()[B");

  /// from: public byte[] getBinaryValue()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Convenience alternative to \#getBinaryValue(Base64Variant)
  /// that defaults to using
  /// Base64Variants\#getDefaultVariant as the default encoding.
  ///@return Decoded binary data
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  jni.JArray<jni.jbyte> getBinaryValue1() {
    return const jni.JArrayType(jni.jbyteType()).fromRef(jni.Jni.accessors
        .callMethodWithArgs(reference.pointer, _id_getBinaryValue1,
            jni.JniCallType.objectType, []).object);
  }

  static final _id_readBinaryValue = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readBinaryValue",
      r"(Ljava/io/OutputStream;)I");

  /// from: public int readBinaryValue(java.io.OutputStream out)
  ///
  /// Method that can be used as an alternative to \#getBigIntegerValue(),
  /// especially when value can be large. The main difference (beyond method
  /// of returning content using OutputStream instead of as byte array)
  /// is that content will NOT remain accessible after method returns: any content
  /// processed will be consumed and is not buffered in any way. If caller needs
  /// buffering, it has to implement it.
  ///@param out Output stream to use for passing decoded binary data
  ///@return Number of bytes that were decoded and written via OutputStream
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  int readBinaryValue(
    jni.JObject out,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readBinaryValue,
        jni.JniCallType.intType,
        [out.reference.pointer]).integer;
  }

  static final _id_readBinaryValue1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readBinaryValue",
      r"(Lcom/fasterxml/jackson/core/Base64Variant;Ljava/io/OutputStream;)I");

  /// from: public int readBinaryValue(com.fasterxml.jackson.core.Base64Variant bv, java.io.OutputStream out)
  ///
  /// Similar to \#readBinaryValue(OutputStream) but allows explicitly
  /// specifying base64 variant to use.
  ///@param bv base64 variant to use
  ///@param out Output stream to use for passing decoded binary data
  ///@return Number of bytes that were decoded and written via OutputStream
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  int readBinaryValue1(
    jni.JObject bv,
    jni.JObject out,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readBinaryValue1,
        jni.JniCallType.intType,
        [bv.reference.pointer, out.reference.pointer]).integer;
  }

  static final _id_getValueAsInt = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsInt", r"()I");

  /// from: public int getValueAsInt()
  ///
  /// Method that will try to convert value of current token to a
  /// Java {@code int} value.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to an int (including structured type
  /// markers like start/end Object/Array)
  /// default value of __0__ will be returned; no exceptions are thrown.
  ///@return {@code int} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsInt() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsInt, jni.JniCallType.intType, []).integer;
  }

  static final _id_getValueAsInt1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsInt", r"(I)I");

  /// from: public int getValueAsInt(int def)
  ///
  /// Method that will try to convert value of current token to a
  /// __int__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to an int (including structured type
  /// markers like start/end Object/Array)
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code int} is not possible
  ///@return {@code int} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsInt1(
    int def,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getValueAsInt1,
        jni.JniCallType.intType,
        [jni.JValueInt(def)]).integer;
  }

  static final _id_getValueAsLong = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsLong", r"()J");

  /// from: public long getValueAsLong()
  ///
  /// Method that will try to convert value of current token to a
  /// __long__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to a long (including structured type
  /// markers like start/end Object/Array)
  /// default value of __0L__ will be returned; no exceptions are thrown.
  ///@return {@code long} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsLong() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsLong, jni.JniCallType.longType, []).long;
  }

  static final _id_getValueAsLong1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsLong", r"(J)J");

  /// from: public long getValueAsLong(long def)
  ///
  /// Method that will try to convert value of current token to a
  /// __long__.
  /// Numbers are coerced using default Java rules; booleans convert to 0 (false)
  /// and 1 (true), and Strings are parsed using default Java language integer
  /// parsing rules.
  ///
  /// If representation can not be converted to a long (including structured type
  /// markers like start/end Object/Array)
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code long} is not possible
  ///@return {@code long} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  int getValueAsLong1(
    int def,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsLong1, jni.JniCallType.longType, [def]).long;
  }

  static final _id_getValueAsDouble = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsDouble", r"()D");

  /// from: public double getValueAsDouble()
  ///
  /// Method that will try to convert value of current token to a Java
  /// __double__.
  /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
  /// and 1.0 (true), and Strings are parsed using default Java language floating
  /// point parsing rules.
  ///
  /// If representation can not be converted to a double (including structured types
  /// like Objects and Arrays),
  /// default value of __0.0__ will be returned; no exceptions are thrown.
  ///@return {@code double} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getValueAsDouble() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsDouble, jni.JniCallType.doubleType, []).doubleFloat;
  }

  static final _id_getValueAsDouble1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsDouble", r"(D)D");

  /// from: public double getValueAsDouble(double def)
  ///
  /// Method that will try to convert value of current token to a
  /// Java __double__.
  /// Numbers are coerced using default Java rules; booleans convert to 0.0 (false)
  /// and 1.0 (true), and Strings are parsed using default Java language floating
  /// point parsing rules.
  ///
  /// If representation can not be converted to a double (including structured types
  /// like Objects and Arrays),
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code double} is not possible
  ///@return {@code double} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  double getValueAsDouble1(
    double def,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsDouble1, jni.JniCallType.doubleType, [def]).doubleFloat;
  }

  static final _id_getValueAsBoolean = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsBoolean", r"()Z");

  /// from: public boolean getValueAsBoolean()
  ///
  /// Method that will try to convert value of current token to a
  /// __boolean__.
  /// JSON booleans map naturally; integer numbers other than 0 map to true, and
  /// 0 maps to false
  /// and Strings 'true' and 'false' map to corresponding values.
  ///
  /// If representation can not be converted to a boolean value (including structured types
  /// like Objects and Arrays),
  /// default value of __false__ will be returned; no exceptions are thrown.
  ///@return {@code boolean} value current token is converted to, if possible; exception thrown
  ///    otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getValueAsBoolean() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_getValueAsBoolean, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getValueAsBoolean1 = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"getValueAsBoolean", r"(Z)Z");

  /// from: public boolean getValueAsBoolean(boolean def)
  ///
  /// Method that will try to convert value of current token to a
  /// __boolean__.
  /// JSON booleans map naturally; integer numbers other than 0 map to true, and
  /// 0 maps to false
  /// and Strings 'true' and 'false' map to corresponding values.
  ///
  /// If representation can not be converted to a boolean value (including structured types
  /// like Objects and Arrays),
  /// specified __def__ will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code boolean} is not possible
  ///@return {@code boolean} value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  bool getValueAsBoolean1(
    bool def,
  ) {
    return jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getValueAsBoolean1,
        jni.JniCallType.booleanType,
        [def ? 1 : 0]).boolean;
  }

  static final _id_getValueAsString = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getValueAsString", r"()Ljava/lang/String;");

  /// from: public java.lang.String getValueAsString()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will try to convert value of current token to a
  /// java.lang.String.
  /// JSON Strings map naturally; scalar values get converted to
  /// their textual representation.
  /// If representation can not be converted to a String value (including structured types
  /// like Objects and Arrays and {@code null} token), default value of
  /// __null__ will be returned; no exceptions are thrown.
  ///@return String value current token is converted to, if possible; {@code null} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  jni.JString getValueAsString() {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getValueAsString,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getValueAsString1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"getValueAsString",
      r"(Ljava/lang/String;)Ljava/lang/String;");

  /// from: public abstract java.lang.String getValueAsString(java.lang.String def)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that will try to convert value of current token to a
  /// java.lang.String.
  /// JSON Strings map naturally; scalar values get converted to
  /// their textual representation.
  /// If representation can not be converted to a String value (including structured types
  /// like Objects and Arrays and {@code null} token), specified default value
  /// will be returned; no exceptions are thrown.
  ///@param def Default value to return if conversion to {@code String} is not possible
  ///@return String value current token is converted to, if possible; {@code def} otherwise
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.1
  jni.JString getValueAsString1(
    jni.JString def,
  ) {
    return const jni.JStringType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getValueAsString1,
        jni.JniCallType.objectType,
        [def.reference.pointer]).object);
  }

  static final _id_canReadObjectId = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"canReadObjectId", r"()Z");

  /// from: public boolean canReadObjectId()
  ///
  /// Introspection method that may be called to see if the underlying
  /// data format supports some kind of Object Ids natively (many do not;
  /// for example, JSON doesn't).
  ///
  /// Default implementation returns true; overridden by data formats
  /// that do support native Object Ids. Caller is expected to either
  /// use a non-native notation (explicit property or such), or fail,
  /// in case it can not use native object ids.
  ///@return {@code True} if the format being read supports native Object Ids;
  ///    {@code false} if not
  ///@since 2.3
  bool canReadObjectId() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_canReadObjectId, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_canReadTypeId = jni.Jni.accessors
      .getMethodIDOf(_class.reference.pointer, r"canReadTypeId", r"()Z");

  /// from: public boolean canReadTypeId()
  ///
  /// Introspection method that may be called to see if the underlying
  /// data format supports some kind of Type Ids natively (many do not;
  /// for example, JSON doesn't).
  ///
  /// Default implementation returns true; overridden by data formats
  /// that do support native Type Ids. Caller is expected to either
  /// use a non-native notation (explicit property or such), or fail,
  /// in case it can not use native type ids.
  ///@return {@code True} if the format being read supports native Type Ids;
  ///    {@code false} if not
  ///@since 2.3
  bool canReadTypeId() {
    return jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_canReadTypeId, jni.JniCallType.booleanType, []).boolean;
  }

  static final _id_getObjectId = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getObjectId", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object getObjectId()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to check whether current token
  /// (one that was just read) has an associated Object id, and if
  /// so, return it.
  /// Note that while typically caller should check with \#canReadObjectId
  /// first, it is not illegal to call this method even if that method returns
  /// true; but if so, it will return null. This may be used to simplify calling
  /// code.
  ///
  /// Default implementation will simply return null.
  ///@return Native Object id associated with the current token, if any; {@code null} if none
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.3
  jni.JObject getObjectId() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getObjectId,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_getTypeId = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer, r"getTypeId", r"()Ljava/lang/Object;");

  /// from: public java.lang.Object getTypeId()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method that can be called to check whether current token
  /// (one that was just read) has an associated type id, and if
  /// so, return it.
  /// Note that while typically caller should check with \#canReadTypeId
  /// first, it is not illegal to call this method even if that method returns
  /// true; but if so, it will return null. This may be used to simplify calling
  /// code.
  ///
  /// Default implementation will simply return null.
  ///@return Native Type Id associated with the current token, if any; {@code null} if none
  ///@throws IOException for low-level read issues, or
  ///   JsonParseException for decoding problems
  ///@since 2.3
  jni.JObject getTypeId() {
    return const jni.JObjectType().fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_getTypeId,
        jni.JniCallType.objectType, []).object);
  }

  static final _id_readValueAs = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readValueAs",
      r"(Ljava/lang/Class;)Ljava/lang/Object;");

  /// from: public T readValueAs(java.lang.Class<T> valueType)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into a non-container
  /// type (it can be an array type, however): typically a bean, array
  /// or a wrapper type (like java.lang.Boolean).
  /// __Note__: method can only be called if the parser has
  /// an object codec assigned; this is true for parsers constructed
  /// by <code>MappingJsonFactory</code> (from "jackson-databind" jar)
  /// but not for JsonFactory (unless its <code>setCodec</code>
  /// method has been explicitly called).
  ///
  /// This method may advance the event stream, for structured types
  /// the current token will be the closing end marker (END_ARRAY,
  /// END_OBJECT) of the bound structure. For non-structured Json types
  /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
  /// stream is not advanced.
  ///
  /// Note: this method should NOT be used if the result type is a
  /// container (java.util.Collection or java.util.Map.
  /// The reason is that due to type erasure, key and value types
  /// can not be introspected when using this method.
  ///@param <T> Nominal type parameter for value type
  ///@param valueType Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Java value read from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAs<$T extends jni.JObject>(
    jni.JObject valueType, {
    required jni.JObjType<$T> T,
  }) {
    return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readValueAs,
        jni.JniCallType.objectType,
        [valueType.reference.pointer]).object);
  }

  static final _id_readValueAs1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readValueAs",
      r"(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/lang/Object;");

  /// from: public T readValueAs(com.fasterxml.jackson.core.type.TypeReference<?> valueTypeRef)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into a Java type, reference
  /// to which is passed as argument. Type is passed using so-called
  /// "super type token"
  /// and specifically needs to be used if the root type is a
  /// parameterized (generic) container type.
  /// __Note__: method can only be called if the parser has
  /// an object codec assigned; this is true for parsers constructed
  /// by <code>MappingJsonFactory</code> (defined in 'jackson-databind' bundle)
  /// but not for JsonFactory (unless its <code>setCodec</code>
  /// method has been explicitly called).
  ///
  /// This method may advance the event stream, for structured types
  /// the current token will be the closing end marker (END_ARRAY,
  /// END_OBJECT) of the bound structure. For non-structured Json types
  /// (and for JsonToken\#VALUE_EMBEDDED_OBJECT)
  /// stream is not advanced.
  ///@param <T> Nominal type parameter for value type
  ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Java value read from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAs1<$T extends jni.JObject>(
    jni.JObject valueTypeRef, {
    required jni.JObjType<$T> T,
  }) {
    return T.fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readValueAs1,
        jni.JniCallType.objectType,
        [valueTypeRef.reference.pointer]).object);
  }

  static final _id_readValuesAs = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readValuesAs",
      r"(Ljava/lang/Class;)Ljava/util/Iterator;");

  /// from: public java.util.Iterator<T> readValuesAs(java.lang.Class<T> valueType)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for reading sequence of Objects from parser stream,
  /// all with same specified value type.
  ///@param <T> Nominal type parameter for value type
  ///@param valueType Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Iterator for reading multiple Java values from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  jni.JIterator<$T> readValuesAs<$T extends jni.JObject>(
    jni.JObject valueType, {
    required jni.JObjType<$T> T,
  }) {
    return jni.JIteratorType(T).fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readValuesAs,
        jni.JniCallType.objectType,
        [valueType.reference.pointer]).object);
  }

  static final _id_readValuesAs1 = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readValuesAs",
      r"(Lcom/fasterxml/jackson/core/type/TypeReference;)Ljava/util/Iterator;");

  /// from: public java.util.Iterator<T> readValuesAs(com.fasterxml.jackson.core.type.TypeReference<T> valueTypeRef)
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method for reading sequence of Objects from parser stream,
  /// all with same specified value type.
  ///@param <T> Nominal type parameter for value type
  ///@param valueTypeRef Java type to read content as (passed to ObjectCodec that
  ///    deserializes content)
  ///@return Iterator for reading multiple Java values from content
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  jni.JIterator<$T> readValuesAs1<$T extends jni.JObject>(
    jni.JObject valueTypeRef, {
    required jni.JObjType<$T> T,
  }) {
    return jni.JIteratorType(T).fromRef(jni.Jni.accessors.callMethodWithArgs(
        reference.pointer,
        _id_readValuesAs1,
        jni.JniCallType.objectType,
        [valueTypeRef.reference.pointer]).object);
  }

  static final _id_readValueAsTree = jni.Jni.accessors.getMethodIDOf(
      _class.reference.pointer,
      r"readValueAsTree",
      r"()Lcom/fasterxml/jackson/core/TreeNode;");

  /// from: public T readValueAsTree()
  /// The returned object must be released after use, by calling the [release] method.
  ///
  /// Method to deserialize JSON content into equivalent "tree model",
  /// represented by root TreeNode of resulting model.
  /// For JSON Arrays it will an array node (with child nodes),
  /// for objects object node (with child nodes), and for other types
  /// matching leaf node type. Empty or whitespace documents are null.
  ///@param <T> Nominal type parameter for result node type (to reduce need for casting)
  ///@return root of the document, or null if empty or whitespace.
  ///@throws IOException if there is either an underlying I/O problem or decoding
  ///    issue at format layer
  $T readValueAsTree<$T extends jni.JObject>({
    required jni.JObjType<$T> T,
  }) {
    return T.fromRef(jni.Jni.accessors.callMethodWithArgs(reference.pointer,
        _id_readValueAsTree, jni.JniCallType.objectType, []).object);
  }
}

final class $JsonParserType extends jni.JObjType<JsonParser> {
  const $JsonParserType();

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

  @override
  JsonParser fromRef(jni.JObjectPtr ref) => JsonParser.fromRef(ref);

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

  @override
  final superCount = 1;

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

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