Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/main/java/dev/zarr/zarrjava/core/Group.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ public static Group open(String path) throws IOException, ZarrException {
}

@Nullable
public abstract Node get(String key) throws ZarrException;
public abstract Node get(String key) throws ZarrException, IOException;

public Stream<Node> list() {
return storeHandle.list()
.map(key -> {
try {
return get(key);
} catch (ZarrException e) {
} catch (Exception e) {
throw new RuntimeException(e);
}
})
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/dev/zarr/zarrjava/store/ConcurrentMemoryStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.zarr.zarrjava.store;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentMemoryStore extends MemoryStore {
@Override
protected Map<List<String>, byte[]> map() {
return new ConcurrentHashMap<>();
}

@Override
public String toString() {
return String.format("<ConcurrentMemoryStore {%s}>", hashCode());
}
}
91 changes: 91 additions & 0 deletions src/main/java/dev/zarr/zarrjava/store/MemoryStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package dev.zarr.zarrjava.store;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.*;
import java.util.stream.Stream;

public class MemoryStore implements Store, Store.ListableStore {
private final Map<List<String>, byte[]> map = map();

protected Map<List<String>, byte[]> map(){
return new HashMap<>();
}

List<String> resolveKeys(String[] keys) {
ArrayList<String> resolvedKeys = new ArrayList<>();
for(String key:keys){
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have a code formatter set up?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the code is not uniformly formatted. Sometimes it's two spaces and sometimes it's tabs.

Copy link
Member Author

@brokkoli71 brokkoli71 Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could format the entire code in a separate PR, so that changes are easier to understand?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, please do.

if(key.startsWith("/")){
key = key.substring(1);
}
resolvedKeys.addAll(Arrays.asList(key.split("/")));
}
return resolvedKeys;
}

@Override
public boolean exists(String[] keys) {
return map.containsKey(resolveKeys(keys));
}

@Nullable
@Override
public ByteBuffer get(String[] keys) {
return get(keys, 0);
}

@Nullable
@Override
public ByteBuffer get(String[] keys, long start) {
return get(keys, start, -1);
}

@Nullable
@Override
public ByteBuffer get(String[] keys, long start, long end) {
byte[] bytes = map.get(resolveKeys(keys));
if (bytes == null) return null;
if (end < 0) end = bytes.length;
if (end > Integer.MAX_VALUE) throw new RuntimeException("TODO"); //TODO
return ByteBuffer.wrap(bytes, (int) start, (int) end);
}


@Override
public void set(String[] keys, ByteBuffer bytes) {
map.put(resolveKeys(keys), bytes.array());
}

@Override
public void delete(String[] keys) {
map.remove(resolveKeys(keys));
}

public Stream<String> list(String[] keys) {
List<String> prefix = resolveKeys(keys);
Set<String> allKeys = new HashSet<>();

for (List<String> k : map.keySet()) {
if (k.size() <= prefix.size() || ! k.subList(0, prefix.size()).equals(prefix))
continue;
for (int i = 0; i < k.size(); i++) {
List<String> subKey = k.subList(0, i+1);
allKeys.add(String.join("/", subKey));
}
}
return allKeys.stream();
}

@Nonnull
@Override
public StoreHandle resolve(String... keys) {
return new StoreHandle(this, keys);
}

@Override
public String toString() {
return String.format("<MemoryStore {%s}>", hashCode());
}
}

11 changes: 11 additions & 0 deletions src/main/java/dev/zarr/zarrjava/v2/Array.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import dev.zarr.zarrjava.ZarrException;
import dev.zarr.zarrjava.core.Attributes;
import dev.zarr.zarrjava.store.FilesystemStore;
import dev.zarr.zarrjava.store.MemoryStore;
import dev.zarr.zarrjava.store.StoreHandle;
import dev.zarr.zarrjava.utils.Utils;
import dev.zarr.zarrjava.core.codec.CodecPipeline;
Expand Down Expand Up @@ -87,6 +88,16 @@ public static Array open(String path) throws IOException, ZarrException {
return open(Paths.get(path));
}

/**
* Creates a new Zarr array with the provided metadata in an in-memory store
*
* @param arrayMetadata the metadata of the Zarr array
* @throws IOException if the metadata cannot be serialized
* @throws ZarrException if the Zarr array cannot be created
*/
public static Array create(ArrayMetadata arrayMetadata) throws ZarrException, IOException {
return create(new StoreHandle(new MemoryStore()), arrayMetadata);
}
/**
* Creates a new Zarr array with the provided metadata at a specified storage location. This
* method will raise an exception if a Zarr array already exists at the specified storage
Expand Down
Loading
Loading