package com.amazon.ionschema.model

import com.amazon.ionschema.model.ContinuousRange.Limit

interface IContinuousRange<T> where T : Comparable<T>, T : Any {
    val start: Limit<T>
    val end: Limit<T>
    operator fun contains(value: T): Boolean
    fun intersect(that: ContinuousRange<T>): Pair<Limit<T>, Limit<T>>?
}

/**
 * A range over a type that is an uncountably infinite set.
 *
 * A `ContinuousRange` is a _bounded interval_ when both limits are non-null, and it is a _half-bounded interval_
 * when one of the limits is `null`. At least one of [start] and [end] must be non-null.
 *
 * A `ContinuousRange` can be _open_, _half-open_, or _closed_ depending on [Limit.exclusive] of the limits.
 *
 * A `ContinuousRange` is allowed to be a _degenerate interval_ (i.e. `start == end` when both limits are closed),
 * but it may not be an empty interval (i.e. `start == end` when either limit is open, or `start > end`).
 */
open class ContinuousRange<T : Comparable<T>> internal constructor(final override val start: Limit<T>, final override val end: Limit<T>) : IContinuousRange<T> {

    private constructor(value: Limit.Closed<T>) : this(value, value)
    internal constructor(value: T) : this(Limit.Closed(value))

    sealed class Limit<out T> {
        abstract val value: T?

        interface Bounded<T> { val value: T }
        data class Closed<T : Comparable<T>>(override val value: T) : Limit<T>(), Bounded<T>
        data class Open<T : Comparable<T>>(override val value: T) : Limit<T>(), Bounded<T>
        object Unbounded : Limit<Nothing>() {
            override val value: Nothing? get() = null

            override fun equals(other: Any?) = other is Unbounded
            override fun hashCode() = 0
        }
    }

    init {
        require(start is Limit.Bounded<*> || end is Limit.Bounded<*>) { "range may not be unbounded both above and below" }
        require(!isEmpty(start, end)) { "range may not be empty" }
    }

    /**
     * Returns the intersection of `this` `DiscreteRange` with [other].
     * If the two ranges do not intersect, returns `null`.
     */
    final override fun intersect(that: ContinuousRange<T>): Pair<Limit<T>, Limit<T>>? {
        val newStart = when {
            this.start is Limit.Unbounded -> that.start
            that.start is Limit.Unbounded -> this.start
            this.start.value!! > that.start.value!! -> this.start
            that.start.value!! > this.start.value!! -> that.start
            this.start is Limit.Open -> this.start
            that.start is Limit.Open -> that.start
            else -> this.start // They are both closed and equal
        }
        val newEnd = when {
            this.end is Limit.Unbounded -> that.end
            that.end is Limit.Unbounded -> this.end
            this.end.value!! < that.end.value!! -> this.end
            that.end.value!! < this.end.value!! -> that.end
            this.end is Limit.Open -> this.end
            that.end is Limit.Open -> that.end
            else -> this.end // They are both closed and equal
        }
        return if (isEmpty(newStart, newEnd)) null else newStart to newEnd
    }

    /**
     * Checks whether the given value is contained within this range.
     */
    final override operator fun contains(value: T): Boolean = start.isBelow(value) && end.isAbove(value)

    private fun Limit<T>.isAbove(other: T) = when (this) {
        is Limit.Closed -> value >= other
        is Limit.Open -> value > other
        is Limit.Unbounded -> true
    }

    private fun Limit<T>.isBelow(other: T) = when (this) {
        is Limit.Closed -> value <= other
        is Limit.Open -> value < other
        is Limit.Unbounded -> true
    }

    /**
     * Checks whether the range is empty. The range is empty if its start value is greater than the end value for
     * non-exclusive endpoints, or if the start value equals the end value when either endpoint is exclusive.
     */
    private fun isEmpty(start: Limit<T>, end: Limit<T>): Boolean {
        if (start is Limit.Unbounded || end is Limit.Unbounded) return false
        val exclusive = start is Limit.Open || end is Limit.Open
        return if (exclusive) start.value!! >= end.value!! else start.value!! > end.value!!
    }

    final override fun toString(): String {
        val lowerBrace = if (start is Limit.Closed) '[' else '('
        val lowerValue = start.value ?: "  "
        val upperValue = end.value ?: "  "
        val upperBrace = if (end is Limit.Closed) ']' else ')'
        return "$lowerBrace$lowerValue,$upperValue$upperBrace"
    }

    final override fun equals(other: Any?): Boolean {
        return other is ContinuousRange<*> &&
            other.start == start &&
            other.end == end
    }

    override fun hashCode(): Int {
        var result = start.hashCode()
        result = 31 * result + end.hashCode()
        return result
    }
}

Compiled from "ContinuousRange.kt"
public final class com.amazon.ionschema.model.ContinuousRange$Limit$Open<T extends java.lang.Comparable<? super T>> extends com.amazon.ionschema.model.ContinuousRange$Limit<T> implements com.amazon.ionschema.model.ContinuousRange$Limit$Bounded<T> {
  private final T value;

  public com.amazon.ionschema.model.ContinuousRange$Limit$Open(T);
    Code:
       0: aload_1
       1: ldc           #13                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aconst_null
       8: invokespecial #22                 // Method com/amazon/ionschema/model/ContinuousRange$Limit."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
      11: aload_0
      12: aload_1
      13: putfield      #25                 // Field value:Ljava/lang/Comparable;
      16: return

  public T getValue();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: areturn

  public final T component1();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: areturn

  public final com.amazon.ionschema.model.ContinuousRange$Limit$Open<T> copy(T);
    Code:
       0: aload_1
       1: ldc           #13                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
       9: dup
      10: aload_1
      11: invokespecial #36                 // Method "<init>":(Ljava/lang/Comparable;)V
      14: areturn

  public static com.amazon.ionschema.model.ContinuousRange$Limit$Open copy$default(com.amazon.ionschema.model.ContinuousRange$Limit$Open, java.lang.Comparable, int, java.lang.Object);
    Code:
       0: iload_2
       1: iconst_1
       2: iand
       3: ifeq          11
       6: aload_0
       7: getfield      #25                 // Field value:Ljava/lang/Comparable;
      10: astore_1
      11: aload_0
      12: aload_1
      13: invokevirtual #40                 // Method copy:(Ljava/lang/Comparable;)Lcom/amazon/ionschema/model/ContinuousRange$Limit$Open;
      16: areturn

  public java.lang.String toString();
    Code:
       0: new           #44                 // class java/lang/StringBuilder
       3: dup
       4: invokespecial #47                 // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #49                 // String Open(value=
       9: invokevirtual #53                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: aload_0
      13: getfield      #25                 // Field value:Ljava/lang/Comparable;
      16: invokevirtual #56                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      19: bipush        41
      21: invokevirtual #59                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      24: invokevirtual #61                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: areturn

  public int hashCode();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: invokevirtual #67                 // Method java/lang/Object.hashCode:()I
       7: ireturn

  public boolean equals(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: if_acmpne     7
       5: iconst_1
       6: ireturn
       7: aload_1
       8: instanceof    #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      11: ifne          16
      14: iconst_0
      15: ireturn
      16: aload_1
      17: checkcast     #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      20: astore_2
      21: aload_0
      22: getfield      #25                 // Field value:Ljava/lang/Comparable;
      25: aload_2
      26: getfield      #25                 // Field value:Ljava/lang/Comparable;
      29: invokestatic  #74                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      32: ifne          37
      35: iconst_0
      36: ireturn
      37: iconst_1
      38: ireturn

  public java.lang.Object getValue();
    Code:
       0: aload_0
       1: invokevirtual #79                 // Method getValue:()Ljava/lang/Comparable;
       4: areturn
}

Compiled from "ContinuousRange.kt"
public final class com.amazon.ionschema.model.ContinuousRange$Limit$Closed<T extends java.lang.Comparable<? super T>> extends com.amazon.ionschema.model.ContinuousRange$Limit<T> implements com.amazon.ionschema.model.ContinuousRange$Limit$Bounded<T> {
  private final T value;

  public com.amazon.ionschema.model.ContinuousRange$Limit$Closed(T);
    Code:
       0: aload_1
       1: ldc           #13                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aconst_null
       8: invokespecial #22                 // Method com/amazon/ionschema/model/ContinuousRange$Limit."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
      11: aload_0
      12: aload_1
      13: putfield      #25                 // Field value:Ljava/lang/Comparable;
      16: return

  public T getValue();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: areturn

  public final T component1();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: areturn

  public final com.amazon.ionschema.model.ContinuousRange$Limit$Closed<T> copy(T);
    Code:
       0: aload_1
       1: ldc           #13                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: new           #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
       9: dup
      10: aload_1
      11: invokespecial #36                 // Method "<init>":(Ljava/lang/Comparable;)V
      14: areturn

  public static com.amazon.ionschema.model.ContinuousRange$Limit$Closed copy$default(com.amazon.ionschema.model.ContinuousRange$Limit$Closed, java.lang.Comparable, int, java.lang.Object);
    Code:
       0: iload_2
       1: iconst_1
       2: iand
       3: ifeq          11
       6: aload_0
       7: getfield      #25                 // Field value:Ljava/lang/Comparable;
      10: astore_1
      11: aload_0
      12: aload_1
      13: invokevirtual #40                 // Method copy:(Ljava/lang/Comparable;)Lcom/amazon/ionschema/model/ContinuousRange$Limit$Closed;
      16: areturn

  public java.lang.String toString();
    Code:
       0: new           #44                 // class java/lang/StringBuilder
       3: dup
       4: invokespecial #47                 // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #49                 // String Closed(value=
       9: invokevirtual #53                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: aload_0
      13: getfield      #25                 // Field value:Ljava/lang/Comparable;
      16: invokevirtual #56                 // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      19: bipush        41
      21: invokevirtual #59                 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      24: invokevirtual #61                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      27: areturn

  public int hashCode();
    Code:
       0: aload_0
       1: getfield      #25                 // Field value:Ljava/lang/Comparable;
       4: invokevirtual #67                 // Method java/lang/Object.hashCode:()I
       7: ireturn

  public boolean equals(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: if_acmpne     7
       5: iconst_1
       6: ireturn
       7: aload_1
       8: instanceof    #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      11: ifne          16
      14: iconst_0
      15: ireturn
      16: aload_1
      17: checkcast     #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      20: astore_2
      21: aload_0
      22: getfield      #25                 // Field value:Ljava/lang/Comparable;
      25: aload_2
      26: getfield      #25                 // Field value:Ljava/lang/Comparable;
      29: invokestatic  #74                 // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      32: ifne          37
      35: iconst_0
      36: ireturn
      37: iconst_1
      38: ireturn

  public java.lang.Object getValue();
    Code:
       0: aload_0
       1: invokevirtual #79                 // Method getValue:()Ljava/lang/Comparable;
       4: areturn
}

Compiled from "ContinuousRange.kt"
public final class com.amazon.ionschema.model.ContinuousRange$Limit$Unbounded extends com.amazon.ionschema.model.ContinuousRange$Limit {
  public static final com.amazon.ionschema.model.ContinuousRange$Limit$Unbounded INSTANCE;

  private com.amazon.ionschema.model.ContinuousRange$Limit$Unbounded();
    Code:
       0: aload_0
       1: aconst_null
       2: invokespecial #9                  // Method com/amazon/ionschema/model/ContinuousRange$Limit."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
       5: return

  public java.lang.Void getValue();
    Code:
       0: aconst_null
       1: areturn

  public boolean equals(java.lang.Object);
    Code:
       0: aload_1
       1: instanceof    #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
       4: ireturn

  public int hashCode();
    Code:
       0: iconst_0
       1: ireturn

  public java.lang.Object getValue();
    Code:
       0: aload_0
       1: invokevirtual #23                 // Method getValue:()Ljava/lang/Void;
       4: areturn

  static {};
    Code:
       0: new           #2                  // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
       3: dup
       4: invokespecial #26                 // Method "<init>":()V
       7: putstatic     #29                 // Field INSTANCE:Lcom/amazon/ionschema/model/ContinuousRange$Limit$Unbounded;
      10: return
}

Compiled from "ContinuousRange.kt"
public class com.amazon.ionschema.model.ContinuousRange<T extends java.lang.Comparable<? super T>> implements com.amazon.ionschema.model.IContinuousRange<T> {
  private final com.amazon.ionschema.model.ContinuousRange$Limit<T> start;

  private final com.amazon.ionschema.model.ContinuousRange$Limit<T> end;

  public com.amazon.ionschema.model.ContinuousRange(com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>, com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>);
    Code:
       0: aload_1
       1: ldc           #13                 // String start
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #21                 // String end
       9: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_0
      13: invokespecial #24                 // Method java/lang/Object."<init>":()V
      16: aload_0
      17: aload_1
      18: putfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      21: aload_0
      22: aload_2
      23: putfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      26: nop
      27: aload_0
      28: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      31: instanceof    #31                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Bounded
      34: ifne          47
      37: aload_0
      38: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      41: instanceof    #31                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Bounded
      44: ifeq          51
      47: iconst_1
      48: goto          52
      51: iconst_0
      52: ifne          72
      55: iconst_0
      56: istore_3
      57: ldc           #33                 // String range may not be unbounded both above and below
      59: astore_3
      60: new           #35                 // class java/lang/IllegalArgumentException
      63: dup
      64: aload_3
      65: invokevirtual #39                 // Method java/lang/Object.toString:()Ljava/lang/String;
      68: invokespecial #42                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
      71: athrow
      72: aload_0
      73: aload_0
      74: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      77: aload_0
      78: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      81: invokespecial #46                 // Method isEmpty:(Lcom/amazon/ionschema/model/ContinuousRange$Limit;Lcom/amazon/ionschema/model/ContinuousRange$Limit;)Z
      84: ifne          91
      87: iconst_1
      88: goto          92
      91: iconst_0
      92: ifne          112
      95: iconst_0
      96: istore_3
      97: ldc           #48                 // String range may not be empty
      99: astore_3
     100: new           #35                 // class java/lang/IllegalArgumentException
     103: dup
     104: aload_3
     105: invokevirtual #39                 // Method java/lang/Object.toString:()Ljava/lang/String;
     108: invokespecial #42                 // Method java/lang/IllegalArgumentException."<init>":(Ljava/lang/String;)V
     111: athrow
     112: nop
     113: return

  public final com.amazon.ionschema.model.ContinuousRange$Limit<T> getStart();
    Code:
       0: aload_0
       1: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
       4: areturn

  public final com.amazon.ionschema.model.ContinuousRange$Limit<T> getEnd();
    Code:
       0: aload_0
       1: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
       4: areturn

  private com.amazon.ionschema.model.ContinuousRange(com.amazon.ionschema.model.ContinuousRange$Limit$Closed<T>);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #55                 // class com/amazon/ionschema/model/ContinuousRange$Limit
       5: aload_1
       6: checkcast     #55                 // class com/amazon/ionschema/model/ContinuousRange$Limit
       9: invokespecial #63                 // Method "<init>":(Lcom/amazon/ionschema/model/ContinuousRange$Limit;Lcom/amazon/ionschema/model/ContinuousRange$Limit;)V
      12: return

  public com.amazon.ionschema.model.ContinuousRange(T);
    Code:
       0: aload_1
       1: ldc           #68                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: new           #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      10: dup
      11: aload_1
      12: invokespecial #72                 // Method com/amazon/ionschema/model/ContinuousRange$Limit$Closed."<init>":(Ljava/lang/Comparable;)V
      15: invokespecial #74                 // Method "<init>":(Lcom/amazon/ionschema/model/ContinuousRange$Limit$Closed;)V
      18: return

  public final kotlin.Pair<com.amazon.ionschema.model.ContinuousRange$Limit<T>, com.amazon.ionschema.model.ContinuousRange$Limit<T>> intersect(com.amazon.ionschema.model.ContinuousRange<T>);
    Code:
       0: aload_1
       1: ldc           #81                 // String that
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: nop
       7: aload_0
       8: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      11: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
      14: ifeq          24
      17: aload_1
      18: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      21: goto          159
      24: aload_1
      25: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      28: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
      31: ifeq          41
      34: aload_0
      35: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      38: goto          159
      41: aload_0
      42: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      45: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      48: dup
      49: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      52: checkcast     #93                 // class java/lang/Comparable
      55: aload_1
      56: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      59: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      62: dup
      63: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      66: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      71: ifle          81
      74: aload_0
      75: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      78: goto          159
      81: aload_1
      82: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      85: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      88: dup
      89: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      92: checkcast     #93                 // class java/lang/Comparable
      95: aload_0
      96: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      99: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
     102: dup
     103: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     106: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
     111: ifle          121
     114: aload_1
     115: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     118: goto          159
     121: aload_0
     122: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     125: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
     128: ifeq          138
     131: aload_0
     132: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     135: goto          159
     138: aload_1
     139: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     142: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
     145: ifeq          155
     148: aload_1
     149: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     152: goto          159
     155: aload_0
     156: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     159: astore_2
     160: nop
     161: aload_0
     162: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     165: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
     168: ifeq          178
     171: aload_1
     172: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     175: goto          313
     178: aload_1
     179: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     182: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
     185: ifeq          195
     188: aload_0
     189: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     192: goto          313
     195: aload_0
     196: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     199: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
     202: dup
     203: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     206: checkcast     #93                 // class java/lang/Comparable
     209: aload_1
     210: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     213: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
     216: dup
     217: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     220: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
     225: ifge          235
     228: aload_0
     229: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     232: goto          313
     235: aload_1
     236: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     239: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
     242: dup
     243: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     246: checkcast     #93                 // class java/lang/Comparable
     249: aload_0
     250: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     253: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
     256: dup
     257: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
     260: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
     265: ifge          275
     268: aload_1
     269: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     272: goto          313
     275: aload_0
     276: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     279: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
     282: ifeq          292
     285: aload_0
     286: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     289: goto          313
     292: aload_1
     293: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     296: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
     299: ifeq          309
     302: aload_1
     303: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     306: goto          313
     309: aload_0
     310: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
     313: astore_3
     314: aload_0
     315: aload_2
     316: aload_3
     317: invokespecial #46                 // Method isEmpty:(Lcom/amazon/ionschema/model/ContinuousRange$Limit;Lcom/amazon/ionschema/model/ContinuousRange$Limit;)Z
     320: ifeq          327
     323: aconst_null
     324: goto          332
     327: aload_2
     328: aload_3
     329: invokestatic  #105                // Method kotlin/TuplesKt.to:(Ljava/lang/Object;Ljava/lang/Object;)Lkotlin/Pair;
     332: areturn

  public final boolean contains(T);
    Code:
       0: aload_1
       1: ldc           #68                 // String value
       3: invokestatic  #19                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_0
       7: aload_0
       8: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      11: aload_1
      12: invokespecial #116                // Method isBelow:(Lcom/amazon/ionschema/model/ContinuousRange$Limit;Ljava/lang/Comparable;)Z
      15: ifeq          34
      18: aload_0
      19: aload_0
      20: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      23: aload_1
      24: invokespecial #119                // Method isAbove:(Lcom/amazon/ionschema/model/ContinuousRange$Limit;Ljava/lang/Comparable;)Z
      27: ifeq          34
      30: iconst_1
      31: goto          35
      34: iconst_0
      35: ireturn

  private final boolean isAbove(com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>, T);
    Code:
       0: aload_1
       1: astore_3
       2: aload_3
       3: instanceof    #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
       6: ifeq          33
       9: aload_1
      10: checkcast     #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      13: invokevirtual #123                // Method com/amazon/ionschema/model/ContinuousRange$Limit$Closed.getValue:()Ljava/lang/Comparable;
      16: aload_2
      17: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      22: iflt          29
      25: iconst_1
      26: goto          83
      29: iconst_0
      30: goto          83
      33: aload_3
      34: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      37: ifeq          64
      40: aload_1
      41: checkcast     #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      44: invokevirtual #124                // Method com/amazon/ionschema/model/ContinuousRange$Limit$Open.getValue:()Ljava/lang/Comparable;
      47: aload_2
      48: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      53: ifle          60
      56: iconst_1
      57: goto          83
      60: iconst_0
      61: goto          83
      64: aload_3
      65: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
      68: ifeq          75
      71: iconst_1
      72: goto          83
      75: new           #126                // class kotlin/NoWhenBranchMatchedException
      78: dup
      79: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
      82: athrow
      83: ireturn

  private final boolean isBelow(com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>, T);
    Code:
       0: aload_1
       1: astore_3
       2: aload_3
       3: instanceof    #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
       6: ifeq          33
       9: aload_1
      10: checkcast     #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      13: invokevirtual #123                // Method com/amazon/ionschema/model/ContinuousRange$Limit$Closed.getValue:()Ljava/lang/Comparable;
      16: aload_2
      17: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      22: ifgt          29
      25: iconst_1
      26: goto          83
      29: iconst_0
      30: goto          83
      33: aload_3
      34: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      37: ifeq          64
      40: aload_1
      41: checkcast     #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      44: invokevirtual #124                // Method com/amazon/ionschema/model/ContinuousRange$Limit$Open.getValue:()Ljava/lang/Comparable;
      47: aload_2
      48: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      53: ifge          60
      56: iconst_1
      57: goto          83
      60: iconst_0
      61: goto          83
      64: aload_3
      65: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
      68: ifeq          75
      71: iconst_1
      72: goto          83
      75: new           #126                // class kotlin/NoWhenBranchMatchedException
      78: dup
      79: invokespecial #127                // Method kotlin/NoWhenBranchMatchedException."<init>":()V
      82: athrow
      83: ireturn

  private final boolean isEmpty(com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>, com.amazon.ionschema.model.ContinuousRange$Limit<? extends T>);
    Code:
       0: aload_1
       1: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
       4: ifne          14
       7: aload_2
       8: instanceof    #83                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Unbounded
      11: ifeq          16
      14: iconst_0
      15: ireturn
      16: aload_1
      17: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      20: ifne          30
      23: aload_2
      24: instanceof    #99                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Open
      27: ifeq          34
      30: iconst_1
      31: goto          35
      34: iconst_0
      35: istore_3
      36: iload_3
      37: ifeq          75
      40: aload_1
      41: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      44: dup
      45: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      48: checkcast     #93                 // class java/lang/Comparable
      51: aload_2
      52: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      55: dup
      56: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      59: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      64: iflt          71
      67: iconst_1
      68: goto          107
      71: iconst_0
      72: goto          107
      75: aload_1
      76: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      79: dup
      80: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      83: checkcast     #93                 // class java/lang/Comparable
      86: aload_2
      87: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      90: dup
      91: invokestatic  #91                 // Method kotlin/jvm/internal/Intrinsics.checkNotNull:(Ljava/lang/Object;)V
      94: invokeinterface #97,  2           // InterfaceMethod java/lang/Comparable.compareTo:(Ljava/lang/Object;)I
      99: ifle          106
     102: iconst_1
     103: goto          107
     106: iconst_0
     107: ireturn

  public final java.lang.String toString();
    Code:
       0: aload_0
       1: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
       4: instanceof    #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
       7: ifeq          15
      10: bipush        91
      12: goto          17
      15: bipush        40
      17: istore_1
      18: aload_0
      19: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      22: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      25: checkcast     #93                 // class java/lang/Comparable
      28: dup
      29: ifnonnull     38
      32: pop
      33: ldc           #135                // String
      35: checkcast     #93                 // class java/lang/Comparable
      38: astore_2
      39: aload_0
      40: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      43: invokevirtual #87                 // Method com/amazon/ionschema/model/ContinuousRange$Limit.getValue:()Ljava/lang/Object;
      46: checkcast     #93                 // class java/lang/Comparable
      49: dup
      50: ifnonnull     59
      53: pop
      54: ldc           #135                // String
      56: checkcast     #93                 // class java/lang/Comparable
      59: astore_3
      60: aload_0
      61: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      64: instanceof    #70                 // class com/amazon/ionschema/model/ContinuousRange$Limit$Closed
      67: ifeq          75
      70: bipush        93
      72: goto          77
      75: bipush        41
      77: istore        4
      79: new           #137                // class java/lang/StringBuilder
      82: dup
      83: invokespecial #138                // Method java/lang/StringBuilder."<init>":()V
      86: iload_1
      87: invokevirtual #142                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      90: aload_2
      91: invokevirtual #145                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      94: bipush        44
      96: invokevirtual #142                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      99: aload_3
     100: invokevirtual #145                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
     103: iload         4
     105: invokevirtual #142                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
     108: invokevirtual #146                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     111: areturn

  public final boolean equals(java.lang.Object);
    Code:
       0: aload_1
       1: instanceof    #2                  // class com/amazon/ionschema/model/ContinuousRange
       4: ifeq          45
       7: aload_1
       8: checkcast     #2                  // class com/amazon/ionschema/model/ContinuousRange
      11: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      14: aload_0
      15: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      18: invokestatic  #157                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      21: ifeq          45
      24: aload_1
      25: checkcast     #2                  // class com/amazon/ionschema/model/ContinuousRange
      28: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      31: aload_0
      32: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      35: invokestatic  #157                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      38: ifeq          45
      41: iconst_1
      42: goto          46
      45: iconst_0
      46: ireturn

  public int hashCode();
    Code:
       0: aload_0
       1: getfield      #27                 // Field start:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
       4: invokevirtual #162                // Method com/amazon/ionschema/model/ContinuousRange$Limit.hashCode:()I
       7: istore_1
       8: bipush        31
      10: iload_1
      11: imul
      12: aload_0
      13: getfield      #29                 // Field end:Lcom/amazon/ionschema/model/ContinuousRange$Limit;
      16: invokevirtual #162                // Method com/amazon/ionschema/model/ContinuousRange$Limit.hashCode:()I
      19: iadd
      20: istore_1
      21: iload_1
      22: ireturn

  public boolean contains(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #93                 // class java/lang/Comparable
       5: invokevirtual #165                // Method contains:(Ljava/lang/Comparable;)Z
       8: ireturn
}

Compiled from "ContinuousRange.kt"
public abstract class com.amazon.ionschema.model.ContinuousRange$Limit<T> {
  private com.amazon.ionschema.model.ContinuousRange$Limit();
    Code:
       0: aload_0
       1: invokespecial #9                  // Method java/lang/Object."<init>":()V
       4: return

  public abstract T getValue();

  public com.amazon.ionschema.model.ContinuousRange$Limit(kotlin.jvm.internal.DefaultConstructorMarker);
    Code:
       0: aload_0
       1: invokespecial #17                 // Method "<init>":()V
       4: return
}

Compiled from "ContinuousRange.kt"
public interface com.amazon.ionschema.model.ContinuousRange$Limit$Bounded<T> {
  public abstract T getValue();
}


package substring

import java.lang.Integer.MAX_VALUE
import kotlin.math.abs

private val IntProgression.length get() = when (this.step) {
    1, -1 -> if (!this.isEmpty()) abs(this.last - this.first) + 1 else 0
    else -> count()
}

class TwoWay {
    internal data class Factorization(val pattern: String,
                                      val left: IntRange,
                                      val right: IntRange,
                                      val rightPeriod: Int) {
        val criticalPosition get() = left.last

        fun leftIsSuffixOfRight(): Boolean {
            return left.all { i -> pattern[i] == pattern[right.first + rightPeriod - left.length + i] }
        }

        init {
            check(criticalPosition >= -1)
            check(left.last + 1 == right.first)
        }
    }

    fun isSubstring(text: String, pattern: String): Boolean {
        when {
            text.isEmpty() -> return pattern.isEmpty()
            pattern.isEmpty() -> return true
        }

        return getAllSubstrings(text, pattern, 1).isNotEmpty()
    }

    internal fun getAllSubstrings(text: String, pattern: String, maxCount: Int = MAX_VALUE): List<Int> {
        when {
            text.isEmpty() -> return emptyList()
            pattern.isEmpty() -> return text.indices.toList()
        }

        val result: MutableList<Int> = mutableListOf()

        val factorization = factorize(pattern)
        if (factorization.leftIsSuffixOfRight()) {
            // CP1
            val (_, left, right, period) = factorization
            var pos = 0
            var memPrefix = -1
            while (pos + pattern.length <= text.length) {
                // Сравнение правой части
                val i = (maxOf(right.first, memPrefix + 1) .. right.last).find { i -> pattern[i] != text[pos + i] }
                if (i != null) {
                    pos = pos + i - right.first + 1
                    memPrefix = -1
                } else {
                    // Сравнение левой части
                    val match = (left.last downTo memPrefix + 1).all { j -> pattern[j] == text[pos + j] }
                    if (match) {
                        result.add(pos)
                        if (result.size >= maxCount) break
                    }
                    pos += period
                    memPrefix = pattern.length - period - 1
                }
            }
        } else {
            // CP2
            val left = factorization.left.reversed()
            val right = factorization.right
            val q = maxOf(left.length, right.length) + 1
            var pos = 0
            while (pos + pattern.length <= text.length) {
                // Сравнение правой части
                val i = right.find { i -> pattern[i] != text[pos + i] }
                if (i != null) {
                    pos = pos + i - right.first + 1
                } else {
                    // Сравнение левой части
                    val match = left.all { j -> pattern[j] == text[pos + j] }
                    if (match) {
                        result.add(pos)
                        if (result.size >= maxCount) break
                    }
                    pos += q
                }
            }
        }
        return result
    }

    private fun factorize(pattern: String): Factorization {
        val naturalOrder = computeMaxSuffixAndPeriod(pattern, naturalOrder())
        val reverseOrder = computeMaxSuffixAndPeriod(pattern, reverseOrder())
        return if (naturalOrder.right.length <= reverseOrder.right.length)
            naturalOrder else reverseOrder
    }

    internal fun computeMaxSuffixAndPeriod(pattern: String, comparator: Comparator<in Char>): Factorization {
        var maxSuffix = -1
        var j = 0
        var k = 1
        var period = 1
        while (j + k < pattern.length) {
            val a = pattern[j + k]
            val b = pattern[maxSuffix + k]
            val abOrder = comparator.compare(a, b)
            when {
                // a < b
                abOrder < 0 -> {
                    j += k
                    k = 1
                    period = j - maxSuffix
                }

                // a == b
                abOrder == 0 -> {
                    if (k != period) {
                        k += 1
                    } else {
                        j += period
                        k = 1
                    }
                }

                // a > b
                else ->  {
                    maxSuffix = j
                    j = maxSuffix + 1
                    k = 1
                    period = 1
                }
            }
        }
        return Factorization(pattern,
                0 .. maxSuffix,
                maxSuffix + 1 .. pattern.lastIndex,
                period
        )
    }
}

Compiled from "TwoWay.kt"
public final class substring.TwoWay {
  public substring.TwoWay();
    Code:
       0: aload_0
       1: invokespecial #8                  // Method java/lang/Object."<init>":()V
       4: return

  public final boolean isSubstring(java.lang.String, java.lang.String);
    Code:
       0: aload_1
       1: ldc           #15                 // String text
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #23                 // String pattern
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: nop
      13: aload_1
      14: checkcast     #25                 // class java/lang/CharSequence
      17: invokeinterface #29,  1           // InterfaceMethod java/lang/CharSequence.length:()I
      22: ifne          29
      25: iconst_1
      26: goto          30
      29: iconst_0
      30: ifeq          51
      33: aload_2
      34: checkcast     #25                 // class java/lang/CharSequence
      37: invokeinterface #29,  1           // InterfaceMethod java/lang/CharSequence.length:()I
      42: ifne          49
      45: iconst_1
      46: goto          50
      49: iconst_0
      50: ireturn
      51: aload_2
      52: checkcast     #25                 // class java/lang/CharSequence
      55: invokeinterface #29,  1           // InterfaceMethod java/lang/CharSequence.length:()I
      60: ifne          67
      63: iconst_1
      64: goto          68
      67: iconst_0
      68: ifeq          73
      71: iconst_1
      72: ireturn
      73: aload_0
      74: aload_1
      75: aload_2
      76: iconst_1
      77: invokevirtual #33                 // Method getAllSubstrings$main:(Ljava/lang/String;Ljava/lang/String;I)Ljava/util/List;
      80: checkcast     #35                 // class java/util/Collection
      83: invokeinterface #39,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
      88: ifne          95
      91: iconst_1
      92: goto          96
      95: iconst_0
      96: ireturn

  public final java.util.List<java.lang.Integer> getAllSubstrings$main(java.lang.String, java.lang.String, int);
    Code:
       0: aload_1
       1: ldc           #15                 // String text
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #23                 // String pattern
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: nop
      13: aload_1
      14: checkcast     #25                 // class java/lang/CharSequence
      17: invokeinterface #29,  1           // InterfaceMethod java/lang/CharSequence.length:()I
      22: ifne          29
      25: iconst_1
      26: goto          30
      29: iconst_0
      30: ifeq          37
      33: invokestatic  #47                 // Method kotlin/collections/CollectionsKt.emptyList:()Ljava/util/List;
      36: areturn
      37: aload_2
      38: checkcast     #25                 // class java/lang/CharSequence
      41: invokeinterface #29,  1           // InterfaceMethod java/lang/CharSequence.length:()I
      46: ifne          53
      49: iconst_1
      50: goto          54
      53: iconst_0
      54: ifeq          71
      57: aload_1
      58: checkcast     #25                 // class java/lang/CharSequence
      61: invokestatic  #53                 // Method kotlin/text/StringsKt.getIndices:(Ljava/lang/CharSequence;)Lkotlin/ranges/IntRange;
      64: checkcast     #55                 // class java/lang/Iterable
      67: invokestatic  #59                 // Method kotlin/collections/CollectionsKt.toList:(Ljava/lang/Iterable;)Ljava/util/List;
      70: areturn
      71: new           #61                 // class java/util/ArrayList
      74: dup
      75: invokespecial #62                 // Method java/util/ArrayList."<init>":()V
      78: checkcast     #64                 // class java/util/List
      81: astore        4
      83: aload_0
      84: aload_2
      85: invokespecial #68                 // Method factorize:(Ljava/lang/String;)Lsubstring/TwoWay$Factorization;
      88: astore        5
      90: aload         5
      92: invokevirtual #73                 // Method substring/TwoWay$Factorization.leftIsSuffixOfRight:()Z
      95: ifeq          439
      98: aload         5
     100: invokevirtual #77                 // Method substring/TwoWay$Factorization.component2:()Lkotlin/ranges/IntRange;
     103: astore        6
     105: aload         5
     107: invokevirtual #80                 // Method substring/TwoWay$Factorization.component3:()Lkotlin/ranges/IntRange;
     110: astore        7
     112: aload         5
     114: invokevirtual #83                 // Method substring/TwoWay$Factorization.component4:()I
     117: istore        8
     119: iconst_0
     120: istore        9
     122: iconst_m1
     123: istore        10
     125: iload         9
     127: aload_2
     128: invokevirtual #86                 // Method java/lang/String.length:()I
     131: iadd
     132: aload_1
     133: invokevirtual #86                 // Method java/lang/String.length:()I
     136: if_icmpgt     750
     139: new           #88                 // class kotlin/ranges/IntRange
     142: dup
     143: aload         7
     145: invokevirtual #91                 // Method kotlin/ranges/IntRange.getFirst:()I
     148: iload         10
     150: iconst_1
     151: iadd
     152: invokestatic  #97                 // Method java/lang/Math.max:(II)I
     155: aload         7
     157: invokevirtual #100                // Method kotlin/ranges/IntRange.getLast:()I
     160: invokespecial #103                // Method kotlin/ranges/IntRange."<init>":(II)V
     163: checkcast     #55                 // class java/lang/Iterable
     166: astore        13
     168: aload         13
     170: invokeinterface #107,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     175: astore        14
     177: aload         14
     179: invokeinterface #112,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     184: ifeq          240
     187: aload         14
     189: invokeinterface #116,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     194: astore        15
     196: aload         15
     198: checkcast     #118                // class java/lang/Number
     201: invokevirtual #121                // Method java/lang/Number.intValue:()I
     204: istore        16
     206: iconst_0
     207: istore        17
     209: aload_2
     210: iload         16
     212: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     215: aload_1
     216: iload         9
     218: iload         16
     220: iadd
     221: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     224: if_icmpeq     231
     227: iconst_1
     228: goto          232
     231: iconst_0
     232: ifeq          177
     235: aload         15
     237: goto          241
     240: aconst_null
     241: checkcast     #127                // class java/lang/Integer
     244: astore        11
     246: aload         11
     248: ifnull        275
     251: iload         9
     253: aload         11
     255: invokevirtual #128                // Method java/lang/Integer.intValue:()I
     258: iadd
     259: aload         7
     261: invokevirtual #91                 // Method kotlin/ranges/IntRange.getFirst:()I
     264: isub
     265: iconst_1
     266: iadd
     267: istore        9
     269: iconst_m1
     270: istore        10
     272: goto          125
     275: aload         6
     277: invokevirtual #100                // Method kotlin/ranges/IntRange.getLast:()I
     280: iload         10
     282: iconst_1
     283: iadd
     284: invokestatic  #134                // Method kotlin/ranges/RangesKt.downTo:(II)Lkotlin/ranges/IntProgression;
     287: checkcast     #55                 // class java/lang/Iterable
     290: astore        13
     292: iconst_0
     293: istore        14
     295: aload         13
     297: instanceof    #35                 // class java/util/Collection
     300: ifeq          320
     303: aload         13
     305: checkcast     #35                 // class java/util/Collection
     308: invokeinterface #39,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
     313: ifeq          320
     316: iconst_1
     317: goto          387
     320: aload         13
     322: invokeinterface #107,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     327: astore        15
     329: aload         15
     331: invokeinterface #112,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     336: ifeq          386
     339: aload         15
     341: checkcast     #136                // class kotlin/collections/IntIterator
     344: invokevirtual #139                // Method kotlin/collections/IntIterator.nextInt:()I
     347: istore        16
     349: iload         16
     351: istore        17
     353: iconst_0
     354: istore        18
     356: aload_2
     357: iload         17
     359: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     362: aload_1
     363: iload         9
     365: iload         17
     367: iadd
     368: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     371: if_icmpne     378
     374: iconst_1
     375: goto          379
     378: iconst_0
     379: ifne          329
     382: iconst_0
     383: goto          387
     386: iconst_1
     387: istore        12
     389: iload         12
     391: ifeq          418
     394: aload         4
     396: iload         9
     398: invokestatic  #143                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     401: invokeinterface #147,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     406: pop
     407: aload         4
     409: invokeinterface #150,  1          // InterfaceMethod java/util/List.size:()I
     414: iload_3
     415: if_icmpge     750
     418: iload         9
     420: iload         8
     422: iadd
     423: istore        9
     425: aload_2
     426: invokevirtual #86                 // Method java/lang/String.length:()I
     429: iload         8
     431: isub
     432: iconst_1
     433: isub
     434: istore        10
     436: goto          125
     439: aload         5
     441: invokevirtual #153                // Method substring/TwoWay$Factorization.getLeft:()Lkotlin/ranges/IntRange;
     444: checkcast     #155                // class kotlin/ranges/IntProgression
     447: invokestatic  #159                // Method kotlin/ranges/RangesKt.reversed:(Lkotlin/ranges/IntProgression;)Lkotlin/ranges/IntProgression;
     450: astore        6
     452: aload         5
     454: invokevirtual #162                // Method substring/TwoWay$Factorization.getRight:()Lkotlin/ranges/IntRange;
     457: astore        7
     459: aload         6
     461: invokestatic  #168                // Method substring/TwoWayKt.access$getLength:(Lkotlin/ranges/IntProgression;)I
     464: aload         7
     466: checkcast     #155                // class kotlin/ranges/IntProgression
     469: invokestatic  #168                // Method substring/TwoWayKt.access$getLength:(Lkotlin/ranges/IntProgression;)I
     472: invokestatic  #97                 // Method java/lang/Math.max:(II)I
     475: iconst_1
     476: iadd
     477: istore        8
     479: iconst_0
     480: istore        9
     482: iload         9
     484: aload_2
     485: invokevirtual #86                 // Method java/lang/String.length:()I
     488: iadd
     489: aload_1
     490: invokevirtual #86                 // Method java/lang/String.length:()I
     493: if_icmpgt     750
     496: aload         7
     498: checkcast     #55                 // class java/lang/Iterable
     501: astore        12
     503: aload         12
     505: invokeinterface #107,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     510: astore        13
     512: aload         13
     514: invokeinterface #112,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     519: ifeq          575
     522: aload         13
     524: invokeinterface #116,  1          // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
     529: astore        14
     531: aload         14
     533: checkcast     #118                // class java/lang/Number
     536: invokevirtual #121                // Method java/lang/Number.intValue:()I
     539: istore        15
     541: iconst_0
     542: istore        16
     544: aload_2
     545: iload         15
     547: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     550: aload_1
     551: iload         9
     553: iload         15
     555: iadd
     556: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     559: if_icmpeq     566
     562: iconst_1
     563: goto          567
     566: iconst_0
     567: ifeq          512
     570: aload         14
     572: goto          576
     575: aconst_null
     576: checkcast     #127                // class java/lang/Integer
     579: astore        10
     581: aload         10
     583: ifnull        607
     586: iload         9
     588: aload         10
     590: invokevirtual #128                // Method java/lang/Integer.intValue:()I
     593: iadd
     594: aload         7
     596: invokevirtual #91                 // Method kotlin/ranges/IntRange.getFirst:()I
     599: isub
     600: iconst_1
     601: iadd
     602: istore        9
     604: goto          482
     607: aload         6
     609: checkcast     #55                 // class java/lang/Iterable
     612: astore        12
     614: iconst_0
     615: istore        13
     617: aload         12
     619: instanceof    #35                 // class java/util/Collection
     622: ifeq          642
     625: aload         12
     627: checkcast     #35                 // class java/util/Collection
     630: invokeinterface #39,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
     635: ifeq          642
     638: iconst_1
     639: goto          709
     642: aload         12
     644: invokeinterface #107,  1          // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
     649: astore        14
     651: aload         14
     653: invokeinterface #112,  1          // InterfaceMethod java/util/Iterator.hasNext:()Z
     658: ifeq          708
     661: aload         14
     663: checkcast     #136                // class kotlin/collections/IntIterator
     666: invokevirtual #139                // Method kotlin/collections/IntIterator.nextInt:()I
     669: istore        15
     671: iload         15
     673: istore        16
     675: iconst_0
     676: istore        17
     678: aload_2
     679: iload         16
     681: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     684: aload_1
     685: iload         9
     687: iload         16
     689: iadd
     690: invokevirtual #125                // Method java/lang/String.charAt:(I)C
     693: if_icmpne     700
     696: iconst_1
     697: goto          701
     700: iconst_0
     701: ifne          651
     704: iconst_0
     705: goto          709
     708: iconst_1
     709: istore        11
     711: iload         11
     713: ifeq          740
     716: aload         4
     718: iload         9
     720: invokestatic  #143                // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     723: invokeinterface #147,  2          // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     728: pop
     729: aload         4
     731: invokeinterface #150,  1          // InterfaceMethod java/util/List.size:()I
     736: iload_3
     737: if_icmpge     750
     740: iload         9
     742: iload         8
     744: iadd
     745: istore        9
     747: goto          482
     750: aload         4
     752: areturn

  public static java.util.List getAllSubstrings$main$default(substring.TwoWay, java.lang.String, java.lang.String, int, int, java.lang.Object);
    Code:
       0: iload         4
       2: iconst_4
       3: iand
       4: ifeq          10
       7: ldc           #198                // int 2147483647
       9: istore_3
      10: aload_0
      11: aload_1
      12: aload_2
      13: iload_3
      14: invokevirtual #33                 // Method getAllSubstrings$main:(Ljava/lang/String;Ljava/lang/String;I)Ljava/util/List;
      17: areturn

  private final substring.TwoWay$Factorization factorize(java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: invokestatic  #204                // Method kotlin/comparisons/ComparisonsKt.naturalOrder:()Ljava/util/Comparator;
       5: invokevirtual #208                // Method computeMaxSuffixAndPeriod$main:(Ljava/lang/String;Ljava/util/Comparator;)Lsubstring/TwoWay$Factorization;
       8: astore_2
       9: aload_0
      10: aload_1
      11: invokestatic  #211                // Method kotlin/comparisons/ComparisonsKt.reverseOrder:()Ljava/util/Comparator;
      14: invokevirtual #208                // Method computeMaxSuffixAndPeriod$main:(Ljava/lang/String;Ljava/util/Comparator;)Lsubstring/TwoWay$Factorization;
      17: astore_3
      18: aload_2
      19: invokevirtual #162                // Method substring/TwoWay$Factorization.getRight:()Lkotlin/ranges/IntRange;
      22: checkcast     #155                // class kotlin/ranges/IntProgression
      25: invokestatic  #168                // Method substring/TwoWayKt.access$getLength:(Lkotlin/ranges/IntProgression;)I
      28: aload_3
      29: invokevirtual #162                // Method substring/TwoWay$Factorization.getRight:()Lkotlin/ranges/IntRange;
      32: checkcast     #155                // class kotlin/ranges/IntProgression
      35: invokestatic  #168                // Method substring/TwoWayKt.access$getLength:(Lkotlin/ranges/IntProgression;)I
      38: if_icmpgt     45
      41: aload_2
      42: goto          46
      45: aload_3
      46: areturn

  public final substring.TwoWay$Factorization computeMaxSuffixAndPeriod$main(java.lang.String, java.util.Comparator<? super java.lang.Character>);
    Code:
       0: aload_1
       1: ldc           #23                 // String pattern
       3: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #214                // String comparator
       9: invokestatic  #21                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: iconst_m1
      13: istore_3
      14: iconst_0
      15: istore        4
      17: iconst_1
      18: istore        5
      20: iconst_1
      21: istore        6
      23: iload         4
      25: iload         5
      27: iadd
      28: aload_1
      29: invokevirtual #86                 // Method java/lang/String.length:()I
      32: if_icmpge     147
      35: aload_1
      36: iload         4
      38: iload         5
      40: iadd
      41: invokevirtual #125                // Method java/lang/String.charAt:(I)C
      44: istore        7
      46: aload_1
      47: iload_3
      48: iload         5
      50: iadd
      51: invokevirtual #125                // Method java/lang/String.charAt:(I)C
      54: istore        8
      56: aload_2
      57: iload         7
      59: invokestatic  #219                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      62: iload         8
      64: invokestatic  #219                // Method java/lang/Character.valueOf:(C)Ljava/lang/Character;
      67: invokeinterface #225,  3          // InterfaceMethod java/util/Comparator.compare:(Ljava/lang/Object;Ljava/lang/Object;)I
      72: istore        9
      74: nop
      75: iload         9
      77: ifge          99
      80: iload         4
      82: iload         5
      84: iadd
      85: istore        4
      87: iconst_1
      88: istore        5
      90: iload         4
      92: iload_3
      93: isub
      94: istore        6
      96: goto          23
      99: iload         9
     101: ifne          130
     104: iload         5
     106: iload         6
     108: if_icmpeq     117
     111: iinc          5, 1
     114: goto          23
     117: iload         4
     119: iload         6
     121: iadd
     122: istore        4
     124: iconst_1
     125: istore        5
     127: goto          23
     130: iload         4
     132: istore_3
     133: iload_3
     134: iconst_1
     135: iadd
     136: istore        4
     138: iconst_1
     139: istore        5
     141: iconst_1
     142: istore        6
     144: goto          23
     147: new           #70                 // class substring/TwoWay$Factorization
     150: dup
     151: aload_1
     152: new           #88                 // class kotlin/ranges/IntRange
     155: dup
     156: iconst_0
     157: iload_3
     158: invokespecial #103                // Method kotlin/ranges/IntRange."<init>":(II)V
     161: new           #88                 // class kotlin/ranges/IntRange
     164: dup
     165: iload_3
     166: iconst_1
     167: iadd
     168: aload_1
     169: checkcast     #25                 // class java/lang/CharSequence
     172: invokestatic  #229                // Method kotlin/text/StringsKt.getLastIndex:(Ljava/lang/CharSequence;)I
     175: invokespecial #103                // Method kotlin/ranges/IntRange."<init>":(II)V
     178: iload         6
     180: invokespecial #232                // Method substring/TwoWay$Factorization."<init>":(Ljava/lang/String;Lkotlin/ranges/IntRange;Lkotlin/ranges/IntRange;I)V
     183: areturn
}

Compiled from "TwoWay.kt"
public final class substring.TwoWayKt {
  private static final int getLength(kotlin.ranges.IntProgression);
    Code:
       0: aload_0
       1: invokevirtual #12                 // Method kotlin/ranges/IntProgression.getStep:()I
       4: tableswitch   { // -1 to 1
                    -1: 32
                     0: 60
                     1: 32
               default: 60
          }
      32: aload_0
      33: invokevirtual #16                 // Method kotlin/ranges/IntProgression.isEmpty:()Z
      36: ifne          56
      39: aload_0
      40: invokevirtual #19                 // Method kotlin/ranges/IntProgression.getLast:()I
      43: aload_0
      44: invokevirtual #22                 // Method kotlin/ranges/IntProgression.getFirst:()I
      47: isub
      48: invokestatic  #28                 // Method java/lang/Math.abs:(I)I
      51: iconst_1
      52: iadd
      53: goto          67
      56: iconst_0
      57: goto          67
      60: aload_0
      61: checkcast     #30                 // class java/lang/Iterable
      64: invokestatic  #36                 // Method kotlin/collections/CollectionsKt.count:(Ljava/lang/Iterable;)I
      67: ireturn

  public static final int access$getLength(kotlin.ranges.IntProgression);
    Code:
       0: aload_0
       1: invokestatic  #41                 // Method getLength:(Lkotlin/ranges/IntProgression;)I
       4: ireturn
}

Compiled from "TwoWay.kt"
public final class substring.TwoWay$Factorization {
  private final java.lang.String pattern;

  private final kotlin.ranges.IntRange left;

  private final kotlin.ranges.IntRange right;

  private final int rightPeriod;

  public substring.TwoWay$Factorization(java.lang.String, kotlin.ranges.IntRange, kotlin.ranges.IntRange, int);
    Code:
       0: aload_1
       1: ldc           #9                  // String pattern
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #17                 // String left
       9: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_3
      13: ldc           #19                 // String right
      15: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: aload_0
      19: invokespecial #22                 // Method java/lang/Object."<init>":()V
      22: aload_0
      23: aload_1
      24: putfield      #25                 // Field pattern:Ljava/lang/String;
      27: aload_0
      28: aload_2
      29: putfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      32: aload_0
      33: aload_3
      34: putfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      37: aload_0
      38: iload         4
      40: putfield      #34                 // Field rightPeriod:I
      43: nop
      44: aload_0
      45: invokevirtual #38                 // Method getCriticalPosition:()I
      48: iconst_m1
      49: if_icmplt     56
      52: iconst_1
      53: goto          57
      56: iconst_0
      57: ifne          70
      60: new           #40                 // class java/lang/IllegalStateException
      63: dup
      64: ldc           #42                 // String Check failed.
      66: invokespecial #45                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
      69: athrow
      70: aload_0
      71: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      74: invokevirtual #50                 // Method kotlin/ranges/IntRange.getLast:()I
      77: iconst_1
      78: iadd
      79: aload_0
      80: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      83: invokevirtual #53                 // Method kotlin/ranges/IntRange.getFirst:()I
      86: if_icmpne     93
      89: iconst_1
      90: goto          94
      93: iconst_0
      94: ifne          107
      97: new           #40                 // class java/lang/IllegalStateException
     100: dup
     101: ldc           #42                 // String Check failed.
     103: invokespecial #45                 // Method java/lang/IllegalStateException."<init>":(Ljava/lang/String;)V
     106: athrow
     107: nop
     108: return

  public final java.lang.String getPattern();
    Code:
       0: aload_0
       1: getfield      #25                 // Field pattern:Ljava/lang/String;
       4: areturn

  public final kotlin.ranges.IntRange getLeft();
    Code:
       0: aload_0
       1: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
       4: areturn

  public final kotlin.ranges.IntRange getRight();
    Code:
       0: aload_0
       1: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
       4: areturn

  public final int getRightPeriod();
    Code:
       0: aload_0
       1: getfield      #34                 // Field rightPeriod:I
       4: ireturn

  public final int getCriticalPosition();
    Code:
       0: aload_0
       1: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
       4: invokevirtual #50                 // Method kotlin/ranges/IntRange.getLast:()I
       7: ireturn

  public final boolean leftIsSuffixOfRight();
    Code:
       0: aload_0
       1: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
       4: checkcast     #67                 // class java/lang/Iterable
       7: astore_1
       8: iconst_0
       9: istore_2
      10: aload_1
      11: instanceof    #69                 // class java/util/Collection
      14: ifeq          33
      17: aload_1
      18: checkcast     #69                 // class java/util/Collection
      21: invokeinterface #72,  1           // InterfaceMethod java/util/Collection.isEmpty:()Z
      26: ifeq          33
      29: iconst_1
      30: goto          123
      33: aload_1
      34: invokeinterface #76,  1           // InterfaceMethod java/lang/Iterable.iterator:()Ljava/util/Iterator;
      39: astore_3
      40: aload_3
      41: invokeinterface #81,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
      46: ifeq          122
      49: aload_3
      50: checkcast     #83                 // class kotlin/collections/IntIterator
      53: invokevirtual #86                 // Method kotlin/collections/IntIterator.nextInt:()I
      56: istore        4
      58: iload         4
      60: istore        5
      62: iconst_0
      63: istore        6
      65: aload_0
      66: getfield      #25                 // Field pattern:Ljava/lang/String;
      69: iload         5
      71: invokevirtual #90                 // Method java/lang/String.charAt:(I)C
      74: aload_0
      75: getfield      #25                 // Field pattern:Ljava/lang/String;
      78: aload_0
      79: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      82: invokevirtual #53                 // Method kotlin/ranges/IntRange.getFirst:()I
      85: aload_0
      86: getfield      #34                 // Field rightPeriod:I
      89: iadd
      90: aload_0
      91: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      94: checkcast     #92                 // class kotlin/ranges/IntProgression
      97: invokestatic  #98                 // Method substring/TwoWayKt.access$getLength:(Lkotlin/ranges/IntProgression;)I
     100: isub
     101: iload         5
     103: iadd
     104: invokevirtual #90                 // Method java/lang/String.charAt:(I)C
     107: if_icmpne     114
     110: iconst_1
     111: goto          115
     114: iconst_0
     115: ifne          40
     118: iconst_0
     119: goto          123
     122: iconst_1
     123: ireturn

  public final java.lang.String component1();
    Code:
       0: aload_0
       1: getfield      #25                 // Field pattern:Ljava/lang/String;
       4: areturn

  public final kotlin.ranges.IntRange component2();
    Code:
       0: aload_0
       1: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
       4: areturn

  public final kotlin.ranges.IntRange component3();
    Code:
       0: aload_0
       1: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
       4: areturn

  public final int component4();
    Code:
       0: aload_0
       1: getfield      #34                 // Field rightPeriod:I
       4: ireturn

  public final substring.TwoWay$Factorization copy(java.lang.String, kotlin.ranges.IntRange, kotlin.ranges.IntRange, int);
    Code:
       0: aload_1
       1: ldc           #9                  // String pattern
       3: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
       6: aload_2
       7: ldc           #17                 // String left
       9: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      12: aload_3
      13: ldc           #19                 // String right
      15: invokestatic  #15                 // Method kotlin/jvm/internal/Intrinsics.checkNotNullParameter:(Ljava/lang/Object;Ljava/lang/String;)V
      18: new           #2                  // class substring/TwoWay$Factorization
      21: dup
      22: aload_1
      23: aload_2
      24: aload_3
      25: iload         4
      27: invokespecial #112                // Method "<init>":(Ljava/lang/String;Lkotlin/ranges/IntRange;Lkotlin/ranges/IntRange;I)V
      30: areturn

  public static substring.TwoWay$Factorization copy$default(substring.TwoWay$Factorization, java.lang.String, kotlin.ranges.IntRange, kotlin.ranges.IntRange, int, int, java.lang.Object);
    Code:
       0: iload         5
       2: iconst_1
       3: iand
       4: ifeq          12
       7: aload_0
       8: getfield      #25                 // Field pattern:Ljava/lang/String;
      11: astore_1
      12: iload         5
      14: iconst_2
      15: iand
      16: ifeq          24
      19: aload_0
      20: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      23: astore_2
      24: iload         5
      26: iconst_4
      27: iand
      28: ifeq          36
      31: aload_0
      32: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      35: astore_3
      36: iload         5
      38: bipush        8
      40: iand
      41: ifeq          50
      44: aload_0
      45: getfield      #34                 // Field rightPeriod:I
      48: istore        4
      50: aload_0
      51: aload_1
      52: aload_2
      53: aload_3
      54: iload         4
      56: invokevirtual #116                // Method copy:(Ljava/lang/String;Lkotlin/ranges/IntRange;Lkotlin/ranges/IntRange;I)Lsubstring/TwoWay$Factorization;
      59: areturn

  public java.lang.String toString();
    Code:
       0: new           #119                // class java/lang/StringBuilder
       3: dup
       4: invokespecial #120                // Method java/lang/StringBuilder."<init>":()V
       7: ldc           #122                // String Factorization(pattern=
       9: invokevirtual #126                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      12: aload_0
      13: getfield      #25                 // Field pattern:Ljava/lang/String;
      16: invokevirtual #126                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: ldc           #128                // String , left=
      21: invokevirtual #126                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: aload_0
      25: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      28: invokevirtual #131                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      31: ldc           #133                // String , right=
      33: invokevirtual #126                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      36: aload_0
      37: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      40: invokevirtual #131                // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder;
      43: ldc           #135                // String , rightPeriod=
      45: invokevirtual #126                // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      48: aload_0
      49: getfield      #34                 // Field rightPeriod:I
      52: invokevirtual #138                // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      55: bipush        41
      57: invokevirtual #141                // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
      60: invokevirtual #143                // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      63: areturn

  public int hashCode();
    Code:
       0: aload_0
       1: getfield      #25                 // Field pattern:Ljava/lang/String;
       4: invokevirtual #146                // Method java/lang/String.hashCode:()I
       7: istore_1
       8: iload_1
       9: bipush        31
      11: imul
      12: aload_0
      13: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      16: invokevirtual #147                // Method kotlin/ranges/IntRange.hashCode:()I
      19: iadd
      20: istore_1
      21: iload_1
      22: bipush        31
      24: imul
      25: aload_0
      26: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      29: invokevirtual #147                // Method kotlin/ranges/IntRange.hashCode:()I
      32: iadd
      33: istore_1
      34: iload_1
      35: bipush        31
      37: imul
      38: aload_0
      39: getfield      #34                 // Field rightPeriod:I
      42: invokestatic  #152                // Method java/lang/Integer.hashCode:(I)I
      45: iadd
      46: istore_1
      47: iload_1
      48: ireturn

  public boolean equals(java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: if_acmpne     7
       5: iconst_1
       6: ireturn
       7: aload_1
       8: instanceof    #2                  // class substring/TwoWay$Factorization
      11: ifne          16
      14: iconst_0
      15: ireturn
      16: aload_1
      17: checkcast     #2                  // class substring/TwoWay$Factorization
      20: astore_2
      21: aload_0
      22: getfield      #25                 // Field pattern:Ljava/lang/String;
      25: aload_2
      26: getfield      #25                 // Field pattern:Ljava/lang/String;
      29: invokestatic  #160                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      32: ifne          37
      35: iconst_0
      36: ireturn
      37: aload_0
      38: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      41: aload_2
      42: getfield      #28                 // Field left:Lkotlin/ranges/IntRange;
      45: invokestatic  #160                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      48: ifne          53
      51: iconst_0
      52: ireturn
      53: aload_0
      54: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      57: aload_2
      58: getfield      #30                 // Field right:Lkotlin/ranges/IntRange;
      61: invokestatic  #160                // Method kotlin/jvm/internal/Intrinsics.areEqual:(Ljava/lang/Object;Ljava/lang/Object;)Z
      64: ifne          69
      67: iconst_0
      68: ireturn
      69: aload_0
      70: getfield      #34                 // Field rightPeriod:I
      73: aload_2
      74: getfield      #34                 // Field rightPeriod:I
      77: if_icmpeq     82
      80: iconst_0
      81: ireturn
      82: iconst_1
      83: ireturn
}