Skip to content

Commit

Permalink
Use conditional types to allow readonly store implementations (aliman…
Browse files Browse the repository at this point in the history
  • Loading branch information
manzt authored Dec 12, 2021
1 parent 3f411ae commit e1893b1
Show file tree
Hide file tree
Showing 8 changed files with 361 additions and 264 deletions.
15 changes: 8 additions & 7 deletions src/lib/hierarchy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import type {
Attrs,
DataType,
Hierarchy,
ReadableStore,
Scalar,
Store,
TypedArray,
TypedArrayConstructor,
} from "../types";
import type { Codec } from "numcodecs";

export class Node<S extends Store, Path extends AbsolutePath> {
export class Node<S extends Store | ReadableStore, Path extends AbsolutePath> {
constructor(public readonly store: S, public readonly path: Path) {}

get name() {
Expand All @@ -22,7 +23,7 @@ export class Node<S extends Store, Path extends AbsolutePath> {
}

export class Group<
S extends Store,
S extends Store | ReadableStore,
H extends Hierarchy<S>,
P extends AbsolutePath = AbsolutePath,
> extends Node<S, P> {
Expand Down Expand Up @@ -85,7 +86,7 @@ export class Group<

interface ExplicitGroupProps<
P extends AbsolutePath,
S extends Store,
S extends Store | ReadableStore,
H extends Hierarchy<S>,
> {
store: S;
Expand All @@ -95,7 +96,7 @@ interface ExplicitGroupProps<
}

export class ExplicitGroup<
S extends Store,
S extends Store | ReadableStore,
H extends Hierarchy<S>,
P extends AbsolutePath = AbsolutePath,
> extends Group<S, H, P> {
Expand All @@ -118,15 +119,15 @@ export class ExplicitGroup<
}

export class ImplicitGroup<
S extends Store,
S extends Store | ReadableStore,
H extends Hierarchy<S>,
P extends AbsolutePath = AbsolutePath,
> extends Group<S, H, P> {}

export interface ZarrArrayProps<
P extends AbsolutePath,
D extends DataType,
S extends Store,
S extends ReadableStore,
> {
store: S;
shape: number[];
Expand All @@ -141,7 +142,7 @@ export interface ZarrArrayProps<

export class ZarrArray<
D extends DataType,
S extends Store,
S extends ReadableStore,
P extends AbsolutePath = AbsolutePath,
> extends Node<S, P> {
readonly shape: number[];
Expand Down
9 changes: 3 additions & 6 deletions src/storage/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import ReadOnlyStore from "./readonly";
import type { AbsolutePath } from "../types";
import type { AbsolutePath, Async, Readable } from "../types";

function resolve(root: string | URL, path: AbsolutePath): URL {
const base = typeof root === "string" ? new URL(root) : root;
Expand All @@ -13,10 +12,8 @@ function resolve(root: string | URL, path: AbsolutePath): URL {
return resolved;
}

class FetchStore extends ReadOnlyStore<RequestInit> {
constructor(public url: string | URL) {
super();
}
class FetchStore implements Async<Readable<RequestInit>> {
constructor(public url: string | URL) {}

async get(key: AbsolutePath, opts: RequestInit = {}): Promise<Uint8Array | undefined> {
const { href } = resolve(this.url, key);
Expand Down
12 changes: 10 additions & 2 deletions src/storage/fs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import * as fs from "node:fs";
import * as path from "node:path";

import type { AbsolutePath, AsyncStore, PrefixPath, RootPath } from "../types";
import type {
AbsolutePath,
Async,
ExtendedReadable,
PrefixPath,
Readable,
RootPath,
Writeable,
} from "../types";

class FileSystemStore implements AsyncStore {
class FileSystemStore implements Async<Readable & Writeable & ExtendedReadable> {
constructor(public root: string) {}

get(key: AbsolutePath): Promise<Uint8Array | undefined> {
Expand Down
11 changes: 9 additions & 2 deletions src/storage/mem.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import type { PrefixPath, RootPath, SyncStore } from "../types";
import type {
ExtendedReadable,
PrefixPath,
Readable,
RootPath,
Writeable,
} from "../types";

class MemoryStore extends Map<string, Uint8Array> implements SyncStore {
class MemoryStore extends Map<string, Uint8Array>
implements Readable, Writeable, ExtendedReadable {
list_prefix(prefix: RootPath | PrefixPath) {
const items = [];
for (const path of super.keys()) {
Expand Down
47 changes: 27 additions & 20 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,30 @@ export interface ListDirResult {
prefixes: string[];
}

export interface SyncStore<GetOptions = any> {
get(key: AbsolutePath, opts?: GetOptions): Uint8Array | undefined;
has(key: AbsolutePath): boolean;
export type Async<T extends Record<string, any>> = {
[Key in keyof T]: (...args: Parameters<T[Key]>) => Promise<ReturnType<T[Key]>>;
};

export interface Readable<Opts = any> {
get(key: AbsolutePath, opts?: Opts): Uint8Array | undefined;
}

export interface Writeable {
set(key: AbsolutePath, value: Uint8Array): void;
delete(key: AbsolutePath): boolean;
list_prefix(key: RootPath | PrefixPath): string[];
list_dir(key?: RootPath | PrefixPath): ListDirResult;
}

export interface AsyncStore<GetOptions = any> {
get(key: AbsolutePath, opts?: GetOptions): Promise<Uint8Array | undefined>;
has(key: AbsolutePath): Promise<boolean>;
set(key: AbsolutePath, value: Uint8Array): Promise<void>;
delete(key: AbsolutePath): Promise<boolean>;
list_prefix(key: RootPath | PrefixPath): Promise<string[]>;
list_dir(key?: RootPath | PrefixPath): Promise<ListDirResult>;
export interface ExtendedReadable extends Readable {
list_prefix(key: RootPath | PrefixPath): string[];
list_dir(key?: RootPath | PrefixPath): ListDirResult;
}

export type Store = SyncStore | AsyncStore;
export type Attrs = Record<string, any>;

export type ArraySelection = null | (number | null | Slice)[];

export interface Hierarchy<Store extends SyncStore | AsyncStore> {
export interface Hierarchy<Store extends Readable | Async<Readable>> {
// read-only
has(path: string): Promise<boolean>;
has(path: AbsolutePath): Promise<boolean>;
get<Path extends AbsolutePath>(path: Path): Promise<
| ZarrArray<DataType, Store, Path>
| ExplicitGroup<Store, Hierarchy<Store>, Path>
Expand All @@ -68,21 +66,30 @@ export interface Hierarchy<Store extends SyncStore | AsyncStore> {
): Promise<ExplicitGroup<Store, Hierarchy<Store>, Path>>;
get_implicit_group<Path extends AbsolutePath>(
path: Path,
): Promise<ImplicitGroup<Store, Hierarchy<Store>, Path>>;
get_children(path?: AbsolutePath): Promise<Map<string, string>>;
): Store extends (ExtendedReadable | Async<ExtendedReadable>)
? Promise<ImplicitGroup<Store, Hierarchy<Store>, Path>>
: never;
get_children(
path?: AbsolutePath,
): Store extends (ExtendedReadable | Async<ExtendedReadable>)
? Promise<Map<string, string>>
: never;

// write
create_group<Path extends AbsolutePath>(
path: Path,
props?: { attrs?: Attrs },
): Promise<ExplicitGroup<Store, Hierarchy<Store>, Path>>;
): Store extends (Writeable | Async<Writeable>)
? Promise<ExplicitGroup<Store, Hierarchy<Store>, Path>>
: never;
create_array<
Path extends AbsolutePath,
Dtype extends DataType,
>(
path: Path,
props: CreateArrayProps<Dtype>,
): Promise<ZarrArray<Dtype, Store, Path>>;
): Store extends (Writeable | Async<Writeable>) ? Promise<ZarrArray<Dtype, Store, Path>>
: never;
}

type RequiredArrayProps<D extends DataType> = {
Expand Down
Loading

0 comments on commit e1893b1

Please sign in to comment.