// Path: core/src/main/java/se/tfiskgul/mux2fs/fs/base/DirectoryFiller.java
// public interface DirectoryFiller {
// 
// 	int add(String name, Path path)
// 			throws IOException;
// 
// 	int addWithExtraSize(String name, Path path, long extraSize)
// 			throws IOException;
// }
// 
// Path: core/src/main/java/se/tfiskgul/mux2fs/fs/base/FileSystem.java
// public interface FileSystem {
// 
// 	String getFSName();
// 
// 	int getattr(String path, StatFiller stat);
// 
// 	int readdir(String path, DirectoryFiller filler);
// 
// 	int readLink(String path, Consumer<String> buf, int size);
// 
// 	int open(String path, FileHandleFiller filler);
// 
// 	int read(String path, Consumer<byte[]> buf, int size, long offset, int fileHandle);
// 
// 	int release(String path, int fileHandle);
// 
// 	void destroy();
// }


import jnr.ffi.types.off_t;
import jnr.ffi.types.size_t;
import ru.serce.jnrfuse.ErrorCodes;
import ru.serce.jnrfuse.FuseFillDir;
import ru.serce.jnrfuse.FuseStubFS;
import ru.serce.jnrfuse.struct.FileStat;
import ru.serce.jnrfuse.struct.FuseFileInfo;
import se.tfiskgul.mux2fs.fs.base.DirectoryFiller;
import se.tfiskgul.mux2fs.fs.base.FileSystem;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.nio.file.Path;
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;

	@Override
	public int readlink(String path, Pointer buf, long size) {
		int intSize = (int) size;
		return delegate.readLink(path, (name) -> buf.putString(0, name, intSize, UTF_8), intSize);
	}

	@Override
	public int open(String path, FuseFileInfo fi) {
		return delegate.open(path, fh -> fi.fh.set(fh));
	}

	@Override
	public int read(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi) {
		if (size >= Integer.MAX_VALUE) {
			return -ErrorCodes.EINVAL();
		}
		return delegate.read(path, (data) -> buf.put(0, data, 0, data.length), (int) size, offset, fi.fh.intValue());
	}

	@Override
	public int release(String path, FuseFileInfo fi) {
		return delegate.release(path, fi.fh.intValue());
	}

	@Override
	public final void destroy(Pointer initResult) {
		delegate.destroy();
	}

// Path: core/src/main/java/se/tfiskgul/mux2fs/fs/base/DirectoryFiller.java
// public interface DirectoryFiller {
// 
// 	int add(String name, Path path)
// 			throws IOException;
// 
// 	int addWithExtraSize(String name, Path path, long extraSize)
// 			throws IOException;
// }
// 
// Path: core/src/main/java/se/tfiskgul/mux2fs/fs/base/FileSystem.java
// public interface FileSystem {
// 
// 	String getFSName();
// 
// 	int getattr(String path, StatFiller stat);
// 
// 	int readdir(String path, DirectoryFiller filler);
// 
// 	int readLink(String path, Consumer<String> buf, int size);
// 
// 	int open(String path, FileHandleFiller filler);
// 
// 	int read(String path, Consumer<byte[]> buf, int size, long offset, int fileHandle);
// 
// 	int release(String path, int fileHandle);
// 
// 	void destroy();
// }


// Path: core/src/main/java/se/tfiskgul/mux2fs/fs/jnrfuse/JnrFuseWrapperFileSystem.java
import jnr.ffi.types.off_t;
import jnr.ffi.types.size_t;
import ru.serce.jnrfuse.ErrorCodes;
import ru.serce.jnrfuse.FuseFillDir;
import ru.serce.jnrfuse.FuseStubFS;
import ru.serce.jnrfuse.struct.FileStat;
import ru.serce.jnrfuse.struct.FuseFileInfo;
import se.tfiskgul.mux2fs.fs.base.DirectoryFiller;
import se.tfiskgul.mux2fs.fs.base.FileSystem;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.nio.file.Path;
import jnr.ffi.Pointer;
import jnr.ffi.Runtime;


	@Override
	public int readlink(String path, Pointer buf, long size) {
		int intSize = (int) size;
		return delegate.readLink(path, (name) -> buf.putString(0, name, intSize, UTF_8), intSize);
	}

	@Override
	public int open(String path, FuseFileInfo fi) {
		return delegate.open(path, fh -> fi.fh.set(fh));
	}

	@Override
	public int read(String path, Pointer buf, @size_t long size, @off_t long offset, FuseFileInfo fi) {
		if (size >= Integer.MAX_VALUE) {
			return -ErrorCodes.EINVAL();
		}
		return delegate.read(path, (data) -> buf.put(0, data, 0, data.length), (int) size, offset, fi.fh.intValue());
	}

	@Override
	public int release(String path, FuseFileInfo fi) {
		return delegate.release(path, fi.fh.intValue());
	}

	@Override
	public final void destroy(Pointer initResult) {
		delegate.destroy();
	}

	private static class FuseDirectoryFiller implements DirectoryFiller {