Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(binding/ocaml): Add support for operator reader and metadata #2881

Merged
merged 4 commits into from
Aug 20, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions bindings/ocaml/build.rs
Expand Up @@ -19,6 +19,9 @@ use std::path::PathBuf;

pub fn main() -> std::io::Result<()> {
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
ocaml_build::Sigs::new("src/seek_from.ml")
.with_source_dir(root.join("src/seek_from"))
.generate()?;
ocaml_build::Sigs::new("src/operator.ml")
.with_source_dir(root.join("src/operator"))
.generate()
Expand Down
1 change: 1 addition & 0 deletions bindings/ocaml/lib/opendal.ml
Expand Up @@ -18,5 +18,6 @@
*)

module Operator = Operator
module Seek_from = Opendal_core.Seek_from
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved

type operator = Opendal_core.Operator.operator
18 changes: 18 additions & 0 deletions bindings/ocaml/lib/operator.ml
Expand Up @@ -18,12 +18,30 @@
*)

let new_operator = Opendal_core.Operator.operator
let stat = Opendal_core.Operator.stat
let is_exist = Opendal_core.Operator.blocking_is_exist
let create_dir = Opendal_core.Operator.blocking_create_dir
let read = Opendal_core.Operator.blocking_read
let reader = Opendal_core.Operator.blocking_reader
Xuanwo marked this conversation as resolved.
Show resolved Hide resolved
let write = Opendal_core.Operator.blocking_write
let copy = Opendal_core.Operator.blocking_copy
let rename = Opendal_core.Operator.blocking_rename
let delete = Opendal_core.Operator.blocking_delete
let remove = Opendal_core.Operator.blocking_remove
let remove_all = Opendal_core.Operator.blocking_remove_all

module Reader = struct
let read = Opendal_core.Operator.reader_read
let seek = Opendal_core.Operator.reader_seek
end

module Metadata = struct
let is_file = Opendal_core.Operator.metadata_is_file
let is_dir = Opendal_core.Operator.metadata_is_dir
let content_length = Opendal_core.Operator.metadata_content_length
let content_md5 = Opendal_core.Operator.metadata_content_md5
let content_type = Opendal_core.Operator.metadata_content_type
let content_disposition = Opendal_core.Operator.metadata_content_disposition
let etag = Opendal_core.Operator.metadata_etag
let last_modified = Opendal_core.Operator.metadata_last_modified
end
60 changes: 60 additions & 0 deletions bindings/ocaml/lib/operator.mli
Expand Up @@ -28,6 +28,17 @@ val new_operator :
@return The block operator
*)

val stat :
Opendal_core.Operator.operator ->
string ->
(Opendal_core.Operator.metadata, string) result
(** [is_exist operator path] Get current path's metadata **without cache** directly.

@param operator The operator
@param path want to stat
@return metadata
*)

val is_exist : Opendal_core.Operator.operator -> string -> (bool, string) result
(** [is_exist operator path] Check if this path exists or not.

Expand Down Expand Up @@ -63,6 +74,17 @@ val read :
@return data of path
*)

val reader :
Opendal_core.Operator.operator ->
string ->
(Opendal_core.Operator.blocking_reader, string) result
(** [read operator path] Create a new reader which can read the whole path.

@param operator The operator
@param path want to read
@return reader
*)

val write :
Opendal_core.Operator.operator -> string -> bytes -> (unit, string) result
(** [write operator path data] Write bytes into given path.
Expand Down Expand Up @@ -117,3 +139,41 @@ val remove_all :
@param operator The block operator
@param path file path
*)

module Reader : sig
val read :
Opendal_core.Operator.blocking_reader -> bytes -> (int, string) result
(** [read reader buf] Read data to [buf] and return data size.*)

val seek :
Opendal_core.Operator.blocking_reader ->
Opendal_core.Seek_from.seek_from ->
(int64, string) result
(** [seek reader pos] is a function that seeks data to the given position [pos].*)
end

module Metadata : sig
val is_file : Opendal_core.Operator.metadata -> bool
(** [is_file metadata] Returns `true` if this metadata is for a file.*)

val is_dir : Opendal_core.Operator.metadata -> bool
(** [is_dir metadata] Returns `true` if this metadata is for a directory.*)

val content_length : Opendal_core.Operator.metadata -> int64
(** [content_length metadata] Content length of this entry.*)

val content_md5 : Opendal_core.Operator.metadata -> string option
(** [content_md5 metadata] Content MD5 of this entry.*)

val content_type : Opendal_core.Operator.metadata -> string option
(** [content_type metadata] Content Type of this entry.*)

val content_disposition : Opendal_core.Operator.metadata -> string option
(** [content_disposition metadata] Content-Disposition of this entry*)

val etag : Opendal_core.Operator.metadata -> string option
(** [etag metadata] ETag of this entry.*)

val last_modified : Opendal_core.Operator.metadata -> int64 option
(** [last_modified metadata] Last modified of this entry.*)
end
1 change: 1 addition & 0 deletions bindings/ocaml/src/lib.rs
Expand Up @@ -22,6 +22,7 @@ use std::str::FromStr;
use ::opendal as od;

mod operator;
mod seek_from;

pub fn new_operator(
scheme_str: String,
Expand Down
25 changes: 24 additions & 1 deletion bindings/ocaml/src/operator.ml
Expand Up @@ -2,16 +2,39 @@

open! Bigarray

(* file: mod.rs *)
(* file: _type.rs *)

type operator
type blocking_reader
type metadata

(* file: metadata.rs *)

external metadata_is_file: metadata -> bool = "metadata_is_file"
external metadata_is_dir: metadata -> bool = "metadata_is_dir"
external metadata_content_length: metadata -> int64 = "metadata_content_length"
external metadata_content_md5: metadata -> string option = "metadata_content_md5"
external metadata_content_type: metadata -> string option = "metadata_content_type"
external metadata_content_disposition: metadata -> string option = "metadata_content_disposition"
external metadata_etag: metadata -> string option = "metadata_etag"
external metadata_last_modified: metadata -> int64 option = "metadata_last_modified"

(* file: mod.rs *)

external operator: string -> (string * string) list -> (operator, string) Result.t = "operator"
external stat: operator -> string -> (metadata, string) Result.t = "stat"
external blocking_is_exist: operator -> string -> (bool, string) Result.t = "blocking_is_exist"
external blocking_create_dir: operator -> string -> (bool, string) Result.t = "blocking_create_dir"
external blocking_read: operator -> string -> (char array, string) Result.t = "blocking_read"
external blocking_reader: operator -> string -> (blocking_reader, string) Result.t = "blocking_reader"
external blocking_write: operator -> string -> bytes -> (unit, string) Result.t = "blocking_write"
external blocking_copy: operator -> string -> string -> (unit, string) Result.t = "blocking_copy"
external blocking_rename: operator -> string -> string -> (unit, string) Result.t = "blocking_rename"
external blocking_delete: operator -> string -> (unit, string) Result.t = "blocking_delete"
external blocking_remove: operator -> string array -> (unit, string) Result.t = "blocking_remove"
external blocking_remove_all: operator -> string -> (unit, string) Result.t = "blocking_remove_all"

(* file: reader.rs *)

external reader_read: blocking_reader -> bytes -> (int, string) Result.t = "reader_read"
external reader_seek: blocking_reader -> Seek_from.seek_from -> (int64, string) Result.t = "reader_seek"
25 changes: 24 additions & 1 deletion bindings/ocaml/src/operator.mli
Expand Up @@ -2,16 +2,39 @@

open! Bigarray

(* file: mod.rs *)
(* file: _type.rs *)

type operator
type blocking_reader
type metadata

(* file: metadata.rs *)

external metadata_is_file: metadata -> bool = "metadata_is_file"
external metadata_is_dir: metadata -> bool = "metadata_is_dir"
external metadata_content_length: metadata -> int64 = "metadata_content_length"
external metadata_content_md5: metadata -> string option = "metadata_content_md5"
external metadata_content_type: metadata -> string option = "metadata_content_type"
external metadata_content_disposition: metadata -> string option = "metadata_content_disposition"
external metadata_etag: metadata -> string option = "metadata_etag"
external metadata_last_modified: metadata -> int64 option = "metadata_last_modified"

(* file: mod.rs *)

external operator: string -> (string * string) list -> (operator, string) Result.t = "operator"
external stat: operator -> string -> (metadata, string) Result.t = "stat"
external blocking_is_exist: operator -> string -> (bool, string) Result.t = "blocking_is_exist"
external blocking_create_dir: operator -> string -> (bool, string) Result.t = "blocking_create_dir"
external blocking_read: operator -> string -> (char array, string) Result.t = "blocking_read"
external blocking_reader: operator -> string -> (blocking_reader, string) Result.t = "blocking_reader"
external blocking_write: operator -> string -> bytes -> (unit, string) Result.t = "blocking_write"
external blocking_copy: operator -> string -> string -> (unit, string) Result.t = "blocking_copy"
external blocking_rename: operator -> string -> string -> (unit, string) Result.t = "blocking_rename"
external blocking_delete: operator -> string -> (unit, string) Result.t = "blocking_delete"
external blocking_remove: operator -> string array -> (unit, string) Result.t = "blocking_remove"
external blocking_remove_all: operator -> string -> (unit, string) Result.t = "blocking_remove_all"

(* file: reader.rs *)

external reader_read: blocking_reader -> bytes -> (int, string) Result.t = "reader_read"
external reader_seek: blocking_reader -> Seek_from.seek_from -> (int64, string) Result.t = "reader_seek"
32 changes: 32 additions & 0 deletions bindings/ocaml/src/operator/_type.rs
@@ -0,0 +1,32 @@
// 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.

// For ocaml-rs, the build order in the same build group is the order of the file names.
// In order to use the type in the function in the generated ocaml file, it must be defined on the first generated file.
use super::*;

#[ocaml::sig]
pub struct Operator(pub(crate) od::BlockingOperator);
ocaml::custom!(Operator);

#[ocaml::sig]
pub struct BlockingReader(pub(crate) od::BlockingReader);
ocaml::custom!(BlockingReader);

#[ocaml::sig]
pub struct Metadata(pub(crate) od::Metadata);
ocaml::custom!(Metadata);
66 changes: 66 additions & 0 deletions bindings/ocaml/src/operator/metadata.rs
@@ -0,0 +1,66 @@
// 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.

use super::*;

#[ocaml::func]
#[ocaml::sig("metadata -> bool ")]
pub fn metadata_is_file(metadata: &mut Metadata) -> bool {
metadata.0.is_file()
}

#[ocaml::func]
#[ocaml::sig("metadata -> bool ")]
pub fn metadata_is_dir(metadata: &mut Metadata) -> bool {
metadata.0.is_dir()
}

#[ocaml::func]
#[ocaml::sig("metadata -> int64 ")]
pub fn metadata_content_length(metadata: &mut Metadata) -> u64 {
metadata.0.content_length()
}

#[ocaml::func]
#[ocaml::sig("metadata -> string option ")]
pub fn metadata_content_md5(metadata: &mut Metadata) -> Option<String> {
metadata.0.content_md5().map(String::from)
}

#[ocaml::func]
#[ocaml::sig("metadata -> string option ")]
pub fn metadata_content_type(metadata: &mut Metadata) -> Option<String> {
metadata.0.content_type().map(String::from)
}

#[ocaml::func]
#[ocaml::sig("metadata -> string option ")]
pub fn metadata_content_disposition(metadata: &mut Metadata) -> Option<String> {
metadata.0.content_disposition().map(String::from)
}

#[ocaml::func]
#[ocaml::sig("metadata -> string option ")]
pub fn metadata_etag(metadata: &mut Metadata) -> Option<String> {
metadata.0.etag().map(String::from)
}

#[ocaml::func]
#[ocaml::sig("metadata -> int64 option ")]
pub fn metadata_last_modified(metadata: &mut Metadata) -> Option<i64> {
metadata.0.last_modified().map(|t| t.timestamp())
}
24 changes: 20 additions & 4 deletions bindings/ocaml/src/operator/mod.rs
Expand Up @@ -15,11 +15,12 @@
// specific language governing permissions and limitations
// under the License.

use super::*;
mod _type;
mod metadata;
mod reader;

#[ocaml::sig]
pub struct Operator(od::BlockingOperator);
ocaml::custom!(Operator);
use super::*;
use _type::*;

#[ocaml::func]
#[ocaml::sig("string -> (string * string) list -> (operator, string) Result.t ")]
Expand All @@ -31,6 +32,12 @@ pub fn operator(
Ok(Operator(op.blocking()).into())
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> (metadata, string) Result.t ")]
pub fn stat(operator: &mut Operator, path: String) -> Result<ocaml::Pointer<Metadata>, String> {
map_res_error(operator.0.stat(path.as_str()).map(|m| Metadata(m).into()))
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> (bool, string) Result.t ")]
pub fn blocking_is_exist(operator: &mut Operator, path: String) -> Result<bool, String> {
Expand All @@ -49,6 +56,15 @@ pub fn blocking_read(operator: &mut Operator, path: String) -> Result<Vec<u8>, S
map_res_error(operator.0.read(path.as_str()))
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> (blocking_reader, string) Result.t ")]
pub fn blocking_reader(
operator: &mut Operator,
path: String,
) -> Result<ocaml::Pointer<BlockingReader>, String> {
map_res_error(operator.0.reader(path.as_str())).map(|op| BlockingReader(op).into())
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> bytes -> (unit, string) Result.t ")]
pub fn blocking_write(
Expand Down
35 changes: 35 additions & 0 deletions bindings/ocaml/src/operator/reader.rs
@@ -0,0 +1,35 @@
// 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.

use std::io;

use super::*;
use seek_from;

use opendal::raw::oio::BlockingRead;

#[ocaml::func]
#[ocaml::sig("blocking_reader -> bytes -> (int, string) Result.t ")]
pub fn reader_read(reader: &mut BlockingReader, buf: &mut [u8]) -> Result<usize, String> {
map_res_error(reader.0.read(buf))
}

#[ocaml::func]
#[ocaml::sig("blocking_reader -> Seek_from.seek_from -> (int64, string) Result.t ")]
pub fn reader_seek(reader: &mut BlockingReader, pos: seek_from::SeekFrom) -> Result<u64, String> {
map_res_error(reader.0.seek(io::SeekFrom::from(pos)))
}