Skip to content

FailedCursor final

final class FailedCursor extends ACursor

Annotations: @immutable

An ACursor representing a failed navigation step.

All navigation methods on a FailedCursor are no-ops that return this, allowing errors to propagate to the point where ACursor.decode is called rather than requiring explicit error checking at each step.

Inheritance

Object → ACursorFailedCursor

Constructors

FailedCursor() const

const FailedCursor(HCursor? lastCursor, CursorOp? lastOp)
Implementation
dart
const FailedCursor(super.lastCursor, super.lastOp);

Properties

failed no setter inherited

bool get failed

Returns true if the cursor is in a failed state.

Inherited from ACursor.

Implementation
dart
bool get failed => !succeeded;

hashCode no setter inherited

int get hashCode

The hash code for this object.

A hash code is a single integer which represents the state of the object that affects operator == comparisons.

All objects have hash codes. The default hash code implemented by Object represents only the identity of the object, the same way as the default operator == implementation only considers objects equal if they are identical (see identityHashCode).

If operator == is overridden to use the object state instead, the hash code must also be changed to represent that state, otherwise the object cannot be used in hash based data structures like the default Set and Map implementations.

Hash codes must be the same for objects that are equal to each other according to operator ==. The hash code of an object should only change if the object changes in a way that affects equality. There are no further requirements for the hash codes. They need not be consistent between executions of the same program and there are no distribution guarantees.

Objects that are not equal are allowed to have the same hash code. It is even technically allowed that all instances have the same hash code, but if clashes happen too often, it may reduce the efficiency of hash-based data structures like HashSet or HashMap.

If a subclass overrides hashCode, it should override the operator == operator as well to maintain consistency.

Inherited from Object.

Implementation
dart
external int get hashCode;

incorrectFocus no setter

bool get incorrectFocus

Returns true if the last operation required a JSON object or array but the cursor was not focused on one (wrong type, not a missing field).

Implementation
dart
bool get incorrectFocus =>
    ((lastOp?.requiresObject ?? false) && !(lastCursor?.value.isObject ?? false)) ||
    ((lastOp?.requiresArray ?? false) && !(lastCursor?.value.isArray ?? false));

index no setter inherited

Option<int> get index

If the cursor is inside a JArray, returns Some with the current index.

Inherited from ACursor.

Implementation
dart
Option<int> get index => none();

key no setter inherited

Option<String> get key

If the cursor is inside a JObject, returns Some with the current key.

Inherited from ACursor.

Implementation
dart
Option<String> get key => none();

keys no setter override

Option<IList<String>> get keys

If the focus is a JObject, returns Some with its keys.

Implementation
dart
@override
Option<IList<String>> get keys => none();

lastCursor final inherited

final HCursor? lastCursor

The cursor that was active before the last operation, or null at the root.

Inherited from ACursor.

Implementation
dart
final HCursor? lastCursor;

lastOp final inherited

final CursorOp? lastOp

The operation that produced this cursor from lastCursor, or null at the root.

Inherited from ACursor.

Implementation
dart
final CursorOp? lastOp;

missingField no setter

bool get missingField

Returns true if the failure was caused by navigating to a field that did not exist (as opposed to a type mismatch).

Implementation
dart
bool get missingField => Option(lastOp).exists((a) => a is Field || a is DownField);

pathString no setter inherited

String get pathString

A dot/bracket string representing the current cursor position (e.g. .user.address[0]).

Inherited from ACursor.

Implementation
dart
String get pathString => PathToRoot.toPathString(pathToRoot());

runtimeType no setter inherited

Type get runtimeType

A representation of the runtime type of the object.

Inherited from Object.

Implementation
dart
external Type get runtimeType;

succeeded no setter override

bool get succeeded

Returns true if the cursor is in a successful state.

Implementation
dart
@override
bool get succeeded => false;

values no setter override

Option<IList<Json>> get values

If the focus is a JArray, returns Some with its elements.

Implementation
dart
@override
Option<IList<Json>> get values => none();

Methods

decode() inherited

DecodeResult<DecodingFailure, A> decode<A>(Decoder<A> decoder)

Decodes the focused value using decoder.

Inherited from ACursor.

Implementation
dart
DecodeResult<A> decode<A>(Decoder<A> decoder) => decoder.tryDecodeC(this);

delete() override

ACursor delete()

Delete the focus and move to the parent.

Implementation
dart
@override
ACursor delete() => this;

downArray() override

ACursor downArray()

If the focus is a JSON array, move to the first element.

Implementation
dart
@override
ACursor downArray() => this;

downField() override

ACursor downField(String key)

If the focus is a JSON object, move to the value at the given key.

Implementation
dart
@override
ACursor downField(String key) => this;

downN() override

ACursor downN(int n)

If the focus is a JSON array, move to element at the given index.

Implementation
dart
@override
ACursor downN(int n) => this;

field() override

ACursor field(String key)

If the focus is a JSON object, move to the sibling at the given key.

Implementation
dart
@override
ACursor field(String key) => this;

focus() override

Option<Json> focus()

Returns Some with the focused Json if the cursor succeeded, or None if it failed.

Implementation
dart
@override
Option<Json> focus() => none();

get() inherited

DecodeResult<DecodingFailure, A> get<A>(String key, Decoder<A> decoder)

Navigates to key and decodes the value using decoder.

Inherited from ACursor.

Implementation
dart
DecodeResult<A> get<A>(String key, Decoder<A> decoder) => downField(key).decode(decoder);

getOrElse() inherited

DecodeResult<DecodingFailure, A> getOrElse<A>(
  String key,
  Decoder<A> decoder,
  A Function() fallback,
)

Navigates to key and decodes the value; returns fallback if the field is absent or decoding yields None.

Inherited from ACursor.

Implementation
dart
DecodeResult<A> getOrElse<A>(String key, Decoder<A> decoder, Function0<A> fallback) =>
    get(key, decoder.optional()).fold(
      (err) => fallback().asRight(),
      (aOpt) => aOpt.fold(() => fallback().asRight(), (a) => a.asRight()),
    );

history() inherited

IList<CursorOp> history()

Returns the list of CursorOps that led to this cursor, most-recent first. Used to reconstruct a path for DecodingFailure messages.

Inherited from ACursor.

Implementation
dart
IList<CursorOp> history() {
  final ops = <CursorOp>[];
  var current = this as ACursor?;

  while (current != null && current.lastOp != null) {
    ops.add(current.lastOp!);
    current = current.lastCursor;
  }

  return ilist(ops);
}

left() override

ACursor left()

If the focus is an element in a JSON array, move to the left.

Implementation
dart
@override
ACursor left() => this;

noSuchMethod() inherited

dynamic noSuchMethod(Invocation invocation)

Invoked when a nonexistent method or property is accessed.

A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:

dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time error

This invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).

Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.

A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:

dart
class MockList<T> implements List<T> {
  noSuchMethod(Invocation invocation) {
    log(invocation);
    super.noSuchMethod(invocation); // Will throw.
  }
}
void main() {
  MockList().add(42);
}

This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.

If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.

The default behavior is to throw a NoSuchMethodError.

Inherited from Object.

Implementation
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);

pathToRoot() inherited

PathToRoot pathToRoot()

Reconstructs the full PathToRoot from the cursor chain.

Inherited from ACursor.

Implementation
dart
PathToRoot pathToRoot() {
  &#47;&#47; TODO: Revisit lastCursorParentOrLastCursor
  var currentCursor = this as ACursor?;
  var acc = PathToRoot.empty;

  while (currentCursor != null) {
    if (currentCursor.failed) {
      &#47;&#47; If the cursor is in a failed state, we lose context on what the
      &#47;&#47; attempted last position was. Since we usually want to know this
      &#47;&#47; for error reporting, we use the lastOp to attempt to recover that
      &#47;&#47; state. We only care about operations which imply a path to the
      &#47;&#47; root, such as a field selection.

      final lastCursor = currentCursor.lastCursor;
      final lastOp = currentCursor.lastOp;

      switch (lastOp) {
        case Field _:
          currentCursor = currentCursor.lastCursor;
          acc = acc.prependElem(PathElem.objectKey(lastOp.key));
        case DownField _:
          &#47;&#47; We tried to move down, and then that failed, so the field was missing.
          currentCursor = currentCursor.lastCursor;
          acc = acc.prependElem(PathElem.objectKey(lastOp.key));
        case DownArray _:
          &#47;&#47; We tried to move into an array, but it must have been empty.
          currentCursor = currentCursor.lastCursor;
          acc = acc.prependElem(PathElem.arrayIndex(0));
        case DownN _:
          &#47;&#47; We tried to move into an array at index N, but there was no element there.
          currentCursor = currentCursor.lastCursor;
          acc = acc.prependElem(PathElem.arrayIndex(lastOp.n));
        case MoveLeft _:
          &#47;&#47; We tried to move to before the start of the array.
          currentCursor = currentCursor.lastCursor;
          acc = acc.prependElem(PathElem.arrayIndex(-1));
        case MoveRight _:
          if (lastCursor is ArrayCursor) {
            &#47;&#47; We tried to move to past the end of the array.
            currentCursor = lastCursor.parent;
            acc = acc.prependElem(PathElem.arrayIndex(lastCursor.indexValue + 1));
          } else {
            &#47;&#47; Invalid state, skip for now.
            currentCursor = currentCursor.lastCursor;
          }
        default:
          &#47;&#47; CursorOp.MoveUp or CursorOp.DeleteGoParent, both are move up
          &#47;&#47; events.
          &#47;&#47;
          &#47;&#47; Recalling we are in a failed branch here, this should only
          &#47;&#47; fail if we are already at the top of the tree or if the
          &#47;&#47; cursor state is broken, in either
          &#47;&#47; case this is the only valid action to take.
          currentCursor = currentCursor.lastCursor;
      }
    } else {
      switch (currentCursor) {
        case ArrayCursor _:
          final cursor = currentCursor;
          currentCursor = cursor.parent;
          acc = acc.prependElem(PathElem.arrayIndex(cursor.indexValue));
        case ObjectCursor _:
          final cursor = currentCursor;
          currentCursor = cursor.parent;
          acc = acc.prependElem(PathElem.objectKey(cursor.keyValue));
        case TopCursor _:
          currentCursor = null; &#47;&#47; Exit loop
        default:
          currentCursor = currentCursor.lastCursor;
      }
    }
  }

  return acc;
}
ACursor right()

If the focus is an element in a JSON array, move to the right.

Implementation
dart
@override
ACursor right() => this;

root() override

HCursor? root()

Returns the root HCursor of the cursor chain, or null if unavailable.

Implementation
dart
@override
HCursor? root() => lastCursor?.root();

set() inherited

ACursor set(Json j)

Returns a new cursor with the focus replaced by j.

Inherited from ACursor.

Implementation
dart
ACursor set(Json j) => withFocus((_) => j);

success() override

Option<HCursor> success()

Returns Some with this cursor if it succeeded, or None if it failed.

Implementation
dart
@override
Option<HCursor> success() => none();

top() override

Option<Json> top()

Returns Some with the root Json value if the cursor succeeded.

Implementation
dart
@override
Option<Json> top() => none();

toString() override

String toString()

A string representation of this object.

Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.

Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.

Implementation
dart
@override
String toString() => 'FailedCursor($lastCursor, $lastOp)';

up() override

ACursor up()

Move focus to the parent.

Implementation
dart
@override
ACursor up() => this;

withFocus() override

ACursor withFocus(Json Function(Json) f)

Returns a new cursor with the focused Json replaced by f(focused).

Implementation
dart
@override
ACursor withFocus(Function1<Json, Json> f) => this;

Operators

operator ==() inherited

bool operator ==(Object other)

The equality operator.

The default behavior for all Objects is to return true if and only if this object and other are the same object.

Override this method to specify a different equality relation on a class. The overriding method must still be an equivalence relation. That is, it must be:

  • Total: It must return a boolean for all arguments. It should never throw.

  • Reflexive: For all objects o, o == o must be true.

  • Symmetric: For all objects o1 and o2, o1 == o2 and o2 == o1 must either both be true, or both be false.

  • Transitive: For all objects o1, o2, and o3, if o1 == o2 and o2 == o3 are true, then o1 == o3 must be true.

The method should also be consistent over time, so whether two objects are equal should only change if at least one of the objects was modified.

If a subclass overrides the equality operator, it should override the hashCode method as well to maintain consistency.

Inherited from Object.

Implementation
dart
external bool operator ==(Object other);