Span.java
package space.sunqian.common.base.value;
import space.sunqian.annotations.Immutable;
import space.sunqian.annotations.Nonnull;
import space.sunqian.annotations.ValueClass;
import java.util.Objects;
/**
* Span consists of a {@code startIndex} inclusive and a {@code endIndex} exclusive, represents a range of a string,
* list or other range-able object. The {@link #equals(Object)} and {@link #hashCode()} are overridden to compare the
* {@code startIndex} and {@code endIndex}.
*
* @author sunqian
*/
@ValueClass
@Immutable
public final class Span {
private static final @Nonnull Span EMPTY = Span.of(0, 0);
/**
* Returns an instance of {@link Span} with the given start index and end index.
*
* @param startIndex the given start index
* @param endIndex the given end index
* @return an instance of {@link Span} with the given start index and end index
* @throws IllegalArgumentException if {@code startIndex > endIndex}
*/
public static @Nonnull Span of(int startIndex, int endIndex) throws IllegalArgumentException {
if (startIndex > endIndex) {
throw new IllegalArgumentException("startIndex must <= endIndex");
}
return new Span(startIndex, endIndex);
}
/**
* Returns an instance of {@link Span} of which {@code startIndex} and {@code endIndex} are both {@code 0}.
*
* @return an instance of {@link Span} of which {@code startIndex} and {@code endIndex} are both {@code 0}
*/
public static @Nonnull Span empty() {
return EMPTY;
}
private final int startIndex;
private final int endIndex;
private Span(int startIndex, int endIndex) {
this.startIndex = startIndex;
this.endIndex = endIndex;
}
/**
* Returns the start index, inclusive.
*
* @return the start index, inclusive
*/
public int startIndex() {
return startIndex;
}
/**
* Returns the end index, exclusive.
*
* @return the end index, exclusive
*/
public int endIndex() {
return endIndex;
}
/**
* Returns {@code true} if {@code startIndex == endIndex}, otherwise {@code false}.
*
* @return {@code true} if {@code startIndex == endIndex}, otherwise {@code false}
*/
public boolean isEmpty() {
return startIndex == endIndex;
}
/**
* Returns the result of {@code endIndex - startIndex}.
*
* @return the result of {@code endIndex - startIndex}
*/
public int length() {
return endIndex - startIndex;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Span)) {
return false;
}
Span span = (Span) o;
return startIndex == span.startIndex && endIndex == span.endIndex;
}
@Override
public int hashCode() {
return Objects.hash(startIndex, endIndex);
}
@Override
public String toString() {
return "[" + startIndex + ", " + endIndex + ")";
}
}