Skip to content

Commit

Permalink
Tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Technici4n committed Feb 20, 2023
1 parent 5072d15 commit 474ff78
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@

/**
* A {@link Storage} implementation made of indexed slots.
* Please note that some storages may not implement this interface:
* checking whether a storage is slotted can be done using {@code instanceof}.
*
* <p>Please note that some storages may not implement this interface.
* It is up to the storage implementation to decide whether to implement this interface or not.
* Checking whether a storage is slotted can be done using {@code instanceof}.
*
* @param <T> The type of the stored resources.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import java.util.Iterator;

import com.google.common.collect.Iterators;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;

Expand Down Expand Up @@ -159,10 +158,17 @@ default long simulateExtract(T resource, long maxAmount, @Nullable TransactionCo
* <p>This can provide a large performance benefit over {@link #iterator()} if the caller is only interested in non-empty views,
* for example because it is trying to extract resources from the storage.
*
* <p>This function should only be overridden if the storage is able to provide an optimized iterator over non-empty views,
* for example because it is keeping an index of non-empty views.
* Otherwise, the default implementation simply calls {@link #iterator()} and filters out empty views.
*
* <p>When implementing this function, note that the guarantees of {@link #iterator()} still apply.
* In particular, {@link #insert} and {@link #extract} may be called safely during iteration.
*
* @return An iterator over the non-empty views of this storage. Calling remove on the iterator is not allowed.
*/
default Iterator<StorageView<T>> nonEmptyIterator() {
return Iterators.filter(iterator(), view -> view.getAmount() > 0 && !view.isResourceBlank());
return TransferApiImpl.filterEmptyViews(iterator());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import org.jetbrains.annotations.ApiStatus;

import net.fabricmc.fabric.api.transfer.v1.storage.Storage;
import net.fabricmc.fabric.api.transfer.v1.storage.SlottedStorage;
import net.fabricmc.fabric.api.transfer.v1.storage.StorageView;
import net.fabricmc.fabric.impl.transfer.TransferApiImpl;

Expand All @@ -34,9 +34,23 @@
* The transfer API is a complex addition, and we want to be able to correct possible design mistakes.
*/
@ApiStatus.Experimental
public interface SingleSlotStorage<T> extends Storage<T>, StorageView<T> {
public interface SingleSlotStorage<T> extends SlottedStorage<T>, StorageView<T> {
@Override
default Iterator<StorageView<T>> iterator() {
return TransferApiImpl.singletonIterator(this);
}

@Override
default int getSlotCount() {
return 1;
}

@Override
default SingleSlotStorage<T> getSlot(int slot) {
if (slot != 0) {
throw new IndexOutOfBoundsException("Slot " + slot + " does not exist in a single-slot storage.");
}

return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,40 @@ public T next() {
}
};
}

public static <T> Iterator<StorageView<T>> filterEmptyViews(Iterator<StorageView<T>> iterator) {
return new Iterator<>() {
StorageView<T> next;

{
findNext();
}

private void findNext() {
while (iterator.hasNext()) {
next = iterator.next();

if (next.getAmount() > 0 && !next.isResourceBlank()) {
return;
}
}

next = null;
}

@Override
public boolean hasNext() {
return next != null;
}

@Override
public StorageView<T> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}

return next;
}
};
}
}

0 comments on commit 474ff78

Please sign in to comment.