Skip to content

Commit

Permalink
feat(binding/ocaml): Add support for operator reader and metadata (#2881
Browse files Browse the repository at this point in the history
)

* add metadata and operator reader

* format code

* update reader seek api

* make lint happy
  • Loading branch information
Ranxy committed Aug 20, 2023
1 parent 876743e commit 84fcc61
Show file tree
Hide file tree
Showing 14 changed files with 432 additions and 6 deletions.
4 changes: 4 additions & 0 deletions bindings/ocaml/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ 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
26 changes: 26 additions & 0 deletions bindings/ocaml/lib/operator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,38 @@
*)

let new_operator = Opendal_core.Operator.operator
let stat = Opendal_core.Operator.blocking_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
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 reader pos mode =
let inner_pos =
match mode with
| Unix.SEEK_CUR -> Opendal_core.Seek_from.Current pos
| Unix.SEEK_END -> Opendal_core.Seek_from.End pos
| Unix.SEEK_SET -> Opendal_core.Seek_from.Start pos
in
Opendal_core.Operator.reader_seek reader inner_pos
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
Original file line number Diff line number Diff line change
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.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.reader -> bytes -> (int, string) result
(** [read reader buf] Read data to [buf] and return data size.*)

val seek :
Opendal_core.Operator.reader ->
int64 ->
Unix.seek_command ->
(int64, string) result
(** [seek reader pos mode] 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,39 @@

open! Bigarray

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

type operator
type 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 blocking_stat: operator -> string -> (metadata, string) Result.t = "blocking_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 -> (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: reader -> bytes -> (int, string) Result.t = "reader_read"
external reader_seek: reader -> Seek_from.seek_from -> (int64, string) Result.t = "reader_seek"
25 changes: 24 additions & 1 deletion bindings/ocaml/src/operator.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,39 @@

open! Bigarray

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

type operator
type 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 blocking_stat: operator -> string -> (metadata, string) Result.t = "blocking_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 -> (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: reader -> bytes -> (int, string) Result.t = "reader_read"
external reader_seek: reader -> Seek_from.seek_from -> (int64, string) Result.t = "reader_seek"
32 changes: 32 additions & 0 deletions bindings/ocaml/src/operator/_type.rs
Original file line number Diff line number Diff line change
@@ -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 Reader(pub(crate) od::BlockingReader);
ocaml::custom!(Reader);

#[ocaml::sig]
pub struct Metadata(pub(crate) od::Metadata);
ocaml::custom!(Metadata);
66 changes: 66 additions & 0 deletions bindings/ocaml/src/operator/metadata.rs
Original file line number Diff line number Diff line change
@@ -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())
}
27 changes: 23 additions & 4 deletions bindings/ocaml/src/operator/mod.rs
Original file line number Diff line number Diff line change
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,15 @@ pub fn operator(
Ok(Operator(op.blocking()).into())
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> (metadata, string) Result.t ")]
pub fn blocking_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 +59,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 -> (reader, string) Result.t ")]
pub fn blocking_reader(
operator: &mut Operator,
path: String,
) -> Result<ocaml::Pointer<Reader>, String> {
map_res_error(operator.0.reader(path.as_str())).map(|op| Reader(op).into())
}

#[ocaml::func]
#[ocaml::sig("operator -> string -> bytes -> (unit, string) Result.t ")]
pub fn blocking_write(
Expand Down

0 comments on commit 84fcc61

Please sign in to comment.