blob: a3fe616fbf0c55a792dd2ba55ffba3c6d6f61f88 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
module opendal.operator;
import std.string: toStringz;
import std.exception: enforce;
import std.conv: to;
import std.parallelism: task, TaskPool;
/// OpenDAL-C binding for D. (unsafe/@system)
private import opendal.opendal_c;
struct Operator
{
private opendal_operator* op;
private TaskPool taskPool;
private bool enabledParallelism;
this(string scheme, OperatorOptions options, bool useParallel = false) @trusted
{
auto result = opendal_operator_new(scheme.toStringz, options.options);
enforce(result.op !is null, "Failed to create Operator");
enforce(result.error is null, "Error in Operator");
op = result.op;
enabledParallelism = useParallel;
if (enabledParallelism)
taskPool = new TaskPool();
}
void write(string path, ubyte[] data) @trusted
{
opendal_bytes bytes = opendal_bytes(data.ptr, data.length, data.length);
auto error = opendal_operator_write(op, path.toStringz, &bytes);
enforce(error is null, "Error writing data");
}
void writeParallel(string path, ubyte[] data) @safe
{
auto t = task!((Operator* op, string p, ubyte[] d) { op.write(p, d); })(&this, path, data);
taskPool.put(t);
t.yieldForce();
}
ubyte[] readParallel(string path) @trusted
{
auto t = task!((Operator* op, string p) { return op.read(p); })(&this, path);
taskPool.put(t);
return t.yieldForce();
}
Entry[] listParallel(string path) @trusted
{
auto t = task!((Operator* op, string p) { return op.list(p); })(&this, path);
taskPool.put(t);
return t.yieldForce();
}
ubyte[] read(string path) @trusted
{
auto result = opendal_operator_read(op, path.toStringz);
enforce(result.error is null, "Error reading data");
scope (exit)
opendal_bytes_free(&result.data);
return result.data.data[0 .. result.data.len].dup;
}
void remove(string path) @trusted
{
auto error = opendal_operator_delete(op, path.toStringz);
enforce(error is null, "Error deleting object");
}
bool exists(string path) @trusted
{
auto result = opendal_operator_exists(op, path.toStringz);
enforce(result.error is null, "Error checking existence");
return result.exists;
}
Metadata stat(string path) @trusted
{
auto result = opendal_operator_stat(op, path.toStringz);
enforce(result.error is null, "Error getting metadata");
return Metadata(result.meta);
}
Entry[] list(string path) @trusted
{
auto result = opendal_operator_list(op, path.toStringz);
enforce(result.error is null, "Error listing objects");
Entry[] entries;
while (true)
{
auto next = opendal_lister_next(result.lister);
if (next.entry is null)
break;
entries ~= Entry(next.entry);
}
return entries;
}
void createDir(string path) @trusted
{
auto error = opendal_operator_create_dir(op, path.toStringz);
enforce(error is null, "Error creating directory");
}
void rename(string src, string dest) @trusted
{
auto error = opendal_operator_rename(op, src.toStringz, dest.toStringz);
enforce(error is null, "Error renaming object");
}
void copy(string src, string dest) @trusted
{
auto error = opendal_operator_copy(op, src.toStringz, dest.toStringz);
enforce(error is null, "Error copying object");
}
~this() @trusted
{
if (op !is null)
opendal_operator_free(op);
if (enabledParallelism)
taskPool.stop();
}
}
class OperatorOptions
{
private opendal_operator_options* options;
this() @trusted
{
options = opendal_operator_options_new();
}
void set(string key, string value) @trusted
{
opendal_operator_options_set(options, key.toStringz, value.toStringz);
}
~this() @trusted
{
if (options !is null)
opendal_operator_options_free(options);
}
}
struct Metadata
{
private opendal_metadata* meta;
this(scope opendal_metadata* meta) @trusted pure
{
this.meta = meta;
}
ulong contentLength() @trusted
{
return opendal_metadata_content_length(meta);
}
bool isFile() @trusted
{
return opendal_metadata_is_file(meta);
}
bool isDir() @trusted
{
return opendal_metadata_is_dir(meta);
}
long lastModified() @trusted
{
return opendal_metadata_last_modified_ms(meta);
}
~this() @trusted
{
if (meta !is null)
opendal_metadata_free(meta);
}
}
struct Entry
{
private opendal_entry* entry;
this(opendal_entry* entry) pure @nogc
{
this.entry = entry;
}
string path()
{
return to!string(opendal_entry_path(entry));
}
string name()
{
return to!string(opendal_entry_name(entry));
}
~this()
{
if (entry !is null)
opendal_entry_free(entry);
}
}