git » sdk » main » tree

[main] / borogove / persistence / MediaStoreFS.hx

package borogove.persistence;

#if cpp
import HaxeCBridge;
#end
import haxe.io.Bytes;
import haxe.io.BytesData;
import sys.FileSystem;
import sys.io.File;
import thenshim.Promise;

#if cpp
@:build(HaxeCBridge.expose())
@:build(HaxeSwiftBridge.expose())
@HaxeCBridge.name("borogove_persistence_media_store_fs")
#end
class MediaStoreFS implements MediaStore {
	private final blobpath: String;
	private var kv: Null<KeyValueStore> = null;

	/**
		Store media on the filesystem

		@param path where on filesystem to store media
	**/
	public function new(path: String) {
		blobpath = path;
	}

	@:allow(borogove)
	private function setKV(kv: KeyValueStore) {
		this.kv = kv;
	}

	/**
		Get absolute path on filesystem to a particular piece of media

		@param uri The URI to the media (ni:// or similar)
		@returns Promise resolving to the path or null
	**/
	public function getMediaPath(uri: String): Promise<Null<String>> {
		final hash = Hash.fromUri(uri);
		if (hash.algorithm == "sha-256") {
			final path = blobpath + "/f" + hash.toHex();
			if (FileSystem.exists(path)) {
				return Promise.resolve(FileSystem.absolutePath(path));
			} else {
				return Promise.resolve(null);
			}
		} else {
			return get(hash.serializeUri()).then(sha256uri -> {
				final sha256 = sha256uri == null ? null : Hash.fromUri(sha256uri);
				if (sha256 == null) {
					return Promise.resolve(null);
				} else {
					return getMediaPath(sha256.toUri());
				}
			});
		}
	}

	@HaxeCBridge.noemit
	public function hasMedia(hashAlgorithm:String, hash:BytesData): Promise<Bool> {
		final hash = new Hash(hashAlgorithm, hash);
		return getMediaPath(hash.toUri()).then(path -> path != null);
	}

	@HaxeCBridge.noemit
	public function removeMedia(hashAlgorithm: String, hash: BytesData) {
		final hash = new Hash(hashAlgorithm, hash);
		getMediaPath(hash.toUri()).then((path) -> {
			if (path != null) FileSystem.deleteFile(path);
		});
	}

	@HaxeCBridge.noemit
	public function storeMedia(mime: String, bd: BytesData): Promise<Bool> {
		final bytes = Bytes.ofData(bd);
		final sha1 = Hash.sha1(bytes);
		final sha256 = Hash.sha256(bytes);
		File.saveBytes(blobpath + "/f" + sha256.toHex(), bytes);
		return thenshim.PromiseTools.all([
			set(sha1.serializeUri(), sha256.serializeUri()),
			set(sha256.serializeUri() + "#contentType", mime)
		]).then(_ -> true);
	}

	private function set(k: String, v: Null<String>) {
		if (kv == null) return Promise.resolve(null);

		return kv.set(k, v);
	}

	private function get(k: String): Promise<Null<String>> {
		if (kv == null) return Promise.resolve(null);

		return kv.get(k);
	}
}