// 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_;
import "../../../../_init.dart";

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

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

  /// 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(_values().object);
  }

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

  /// 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(_valueOf(name.reference.pointer).object);
  }

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

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

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

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

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

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

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

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

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

  /// 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(_values().object);
  }

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

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

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

  /// 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(_get_DEFAULT_READ_CAPABILITIES().object);

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

  /// from: protected void <init>()
  /// The returned object must be released after use, by calling the [release] method.
  factory JsonParser() {
    return JsonParser.fromRef(_new0().object);
  }

  static final _new1 =
      jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32)>>(
              "JsonParser__new1")
          .asFunction<jni.JniResult Function(int)>();

  /// 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(_new1(features).object);
  }

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

  /// 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(_getCodec(reference.pointer).object);
  }

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

  /// 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 _setCodec(reference.pointer, oc.reference.pointer).check();
  }

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

  /// 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(_getInputSource(reference.pointer).object);
  }

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

  /// 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 _setRequestPayloadOnError(
            reference.pointer, payload.reference.pointer)
        .check();
  }

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

  /// 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 _setRequestPayloadOnError1(reference.pointer,
            payload.reference.pointer, charset.reference.pointer)
        .check();
  }

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

  /// 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 _setRequestPayloadOnError2(
            reference.pointer, payload.reference.pointer)
        .check();
  }

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

  /// 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 _setSchema(reference.pointer, schema.reference.pointer).check();
  }

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

  /// 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(_getSchema(reference.pointer).object);
  }

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

  /// from: public boolean canUseSchema(com.fasterxml.jackson.core.FormatSchema schema)
  ///
  /// Method that can be used to 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 _canUseSchema(reference.pointer, schema.reference.pointer).boolean;
  }

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

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

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

  /// 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 _canParseAsync(reference.pointer).boolean;
  }

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

  /// 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(_getNonBlockingInputFeeder(reference.pointer).object);
  }

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

  /// 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(_getReadCapabilities(reference.pointer).object);
  }

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

  /// 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(_version(reference.pointer).object);
  }

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

  /// 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 _close(reference.pointer).check();
  }

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

  /// 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 _isClosed(reference.pointer).boolean;
  }

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

  /// 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(_getParsingContext(reference.pointer).object);
  }

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

  /// 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(_currentLocation(reference.pointer).object);
  }

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

  /// 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(_currentTokenLocation(reference.pointer).object);
  }

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

  /// 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(_getCurrentLocation(reference.pointer).object);
  }

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

  /// 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(_getTokenLocation(reference.pointer).object);
  }

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

  /// 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(_currentValue(reference.pointer).object);
  }

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

  /// 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 _assignCurrentValue(reference.pointer, v.reference.pointer).check();
  }

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

  /// 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(_getCurrentValue(reference.pointer).object);
  }

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

  /// 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 _setCurrentValue(reference.pointer, v.reference.pointer).check();
  }

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

  /// 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 _releaseBuffered(reference.pointer, out.reference.pointer).integer;
  }

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

  /// 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 _releaseBuffered1(reference.pointer, w.reference.pointer).integer;
  }

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

  /// 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(_enable(reference.pointer, f.reference.pointer).object);
  }

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

  /// 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(_disable(reference.pointer, f.reference.pointer).object);
  }

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

  /// 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(
        _configure(reference.pointer, f.reference.pointer, state ? 1 : 0)
            .object);
  }

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

  /// 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 _isEnabled(reference.pointer, f.reference.pointer).boolean;
  }

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

  /// 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 _isEnabled1(reference.pointer, f.reference.pointer).boolean;
  }

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

  /// 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 _getFeatureMask(reference.pointer).integer;
  }

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

  /// 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(_setFeatureMask(reference.pointer, mask).object);
  }

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

  /// 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(_overrideStdFeatures(reference.pointer, values, mask).object);
  }

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

  /// 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 _getFormatFeatures(reference.pointer).integer;
  }

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

  /// 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(
        _overrideFormatFeatures(reference.pointer, values, mask).object);
  }

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

  /// 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(_nextToken(reference.pointer).object);
  }

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

  /// 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(_nextValue(reference.pointer).object);
  }

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

  /// 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 _nextFieldName(reference.pointer, str.reference.pointer).boolean;
  }

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

  /// 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(_nextFieldName1(reference.pointer).object);
  }

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

  /// 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(_nextTextValue(reference.pointer).object);
  }

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

  /// 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 _nextIntValue(reference.pointer, defaultValue).integer;
  }

  static final _nextLongValue = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int64)>>("JsonParser__nextLongValue")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// 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 _nextLongValue(reference.pointer, defaultValue).long;
  }

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

  /// 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(_nextBooleanValue(reference.pointer).object);
  }

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

  /// 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(_skipChildren(reference.pointer).object);
  }

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

  /// 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 _finishToken(reference.pointer).check();
  }

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

  /// 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(_currentToken(reference.pointer).object);
  }

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

  /// 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 _currentTokenId(reference.pointer).integer;
  }

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

  /// 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(_getCurrentToken(reference.pointer).object);
  }

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

  /// 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 _getCurrentTokenId(reference.pointer).integer;
  }

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

  /// 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 _hasCurrentToken(reference.pointer).boolean;
  }

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

  /// 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 _hasTokenId(reference.pointer, id).boolean;
  }

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

  /// 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 _hasToken(reference.pointer, t.reference.pointer).boolean;
  }

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

  /// 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 _isExpectedStartArrayToken(reference.pointer).boolean;
  }

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

  /// 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 _isExpectedStartObjectToken(reference.pointer).boolean;
  }

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

  /// 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 _isExpectedNumberIntToken(reference.pointer).boolean;
  }

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

  /// 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 _isNaN(reference.pointer).boolean;
  }

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

  /// 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 _clearCurrentToken(reference.pointer).check();
  }

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

  /// 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(_getLastClearedToken(reference.pointer).object);
  }

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

  /// 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 _overrideCurrentName(reference.pointer, name.reference.pointer)
        .check();
  }

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

  /// 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(_getCurrentName(reference.pointer).object);
  }

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

  /// 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(_currentName(reference.pointer).object);
  }

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

  /// 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(_getText(reference.pointer).object);
  }

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

  /// 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 _getText1(reference.pointer, writer.reference.pointer).integer;
  }

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

  /// 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(_getTextCharacters(reference.pointer).object);
  }

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

  /// 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 _getTextLength(reference.pointer).integer;
  }

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

  /// 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 _getTextOffset(reference.pointer).integer;
  }

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

  /// 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 _hasTextCharacters(reference.pointer).boolean;
  }

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

  /// 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(_getNumberValue(reference.pointer).object);
  }

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

  /// 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(_getNumberValueExact(reference.pointer).object);
  }

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

  /// 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(_getNumberType(reference.pointer).object);
  }

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

  /// 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 _getByteValue(reference.pointer).byte;
  }

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

  /// 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 _getShortValue(reference.pointer).short;
  }

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

  /// 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 _getIntValue(reference.pointer).integer;
  }

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

  /// 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 _getLongValue(reference.pointer).long;
  }

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

  /// 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(_getBigIntegerValue(reference.pointer).object);
  }

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

  /// 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 _getFloatValue(reference.pointer).float;
  }

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

  /// 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 _getDoubleValue(reference.pointer).doubleFloat;
  }

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

  /// 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(_getDecimalValue(reference.pointer).object);
  }

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

  /// 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 _getBooleanValue(reference.pointer).boolean;
  }

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

  /// 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(_getEmbeddedObject(reference.pointer).object);
  }

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

  /// 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(
        _getBinaryValue(reference.pointer, bv.reference.pointer).object);
  }

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

  /// 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(_getBinaryValue1(reference.pointer).object);
  }

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

  /// 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 _readBinaryValue(reference.pointer, out.reference.pointer).integer;
  }

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

  /// 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 _readBinaryValue1(
            reference.pointer, bv.reference.pointer, out.reference.pointer)
        .integer;
  }

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

  /// 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 _getValueAsInt(reference.pointer).integer;
  }

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

  /// 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 _getValueAsInt1(reference.pointer, def).integer;
  }

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

  /// 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 _getValueAsLong(reference.pointer).long;
  }

  static final _getValueAsLong1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Int64)>>("JsonParser__getValueAsLong1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, int)>();

  /// 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 _getValueAsLong1(reference.pointer, def).long;
  }

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

  /// 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 _getValueAsDouble(reference.pointer).doubleFloat;
  }

  static final _getValueAsDouble1 = jniLookup<
          ffi.NativeFunction<
              jni.JniResult Function(ffi.Pointer<ffi.Void>,
                  ffi.Double)>>("JsonParser__getValueAsDouble1")
      .asFunction<jni.JniResult Function(ffi.Pointer<ffi.Void>, double)>();

  /// 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 _getValueAsDouble1(reference.pointer, def).doubleFloat;
  }

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

  /// 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 _getValueAsBoolean(reference.pointer).boolean;
  }

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

  /// 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 _getValueAsBoolean1(reference.pointer, def ? 1 : 0).boolean;
  }

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

  /// 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(_getValueAsString(reference.pointer).object);
  }

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

  /// 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(
        _getValueAsString1(reference.pointer, def.reference.pointer).object);
  }

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

  /// 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 _canReadObjectId(reference.pointer).boolean;
  }

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

  /// 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 _canReadTypeId(reference.pointer).boolean;
  }

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

  /// 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(_getObjectId(reference.pointer).object);
  }

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

  /// 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(_getTypeId(reference.pointer).object);
  }

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

  /// 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(
        _readValueAs(reference.pointer, valueType.reference.pointer).object);
  }

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

  /// 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(
        _readValueAs1(reference.pointer, valueTypeRef.reference.pointer)
            .object);
  }

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

  /// 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(
        _readValuesAs(reference.pointer, valueType.reference.pointer).object);
  }

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

  /// 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(
        _readValuesAs1(reference.pointer, valueTypeRef.reference.pointer)
            .object);
  }

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

  /// 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(_readValueAsTree(reference.pointer).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;
  }
}
