You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by yu...@apache.org on 2024/09/24 11:11:28 UTC
(opendal) 02/02: feat(bindings/go): add writer operation
This is an automated email from the ASF dual-hosted git repository.
yuchanns pushed a commit to branch feat-c-binding-writer
in repository https://gitbox.apache.org/repos/asf/opendal.git
commit ab9bbae313559b7664cf486d26b3626d0654b6c9
Author: Hanchin Hsieh <me...@yuchanns.xyz>
AuthorDate: Tue Sep 24 19:10:56 2024 +0800
feat(bindings/go): add writer operation
Signed-off-by: Hanchin Hsieh <me...@yuchanns.xyz>
---
bindings/go/types.go | 21 +++++++
bindings/go/write.go | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 183 insertions(+)
diff --git a/bindings/go/types.go b/bindings/go/types.go
index 49c0daf5d3..4ee2de1884 100644
--- a/bindings/go/types.go
+++ b/bindings/go/types.go
@@ -89,6 +89,15 @@ var (
}[0],
}
+ typeResultWriterWrite = ffi.Type{
+ Type: ffi.Struct,
+ Elements: &[]*ffi.Type{
+ &ffi.TypePointer,
+ &ffi.TypePointer,
+ nil,
+ }[0],
+ }
+
typeResultReaderRead = ffi.Type{
Type: ffi.Struct,
Elements: &[]*ffi.Type{
@@ -209,6 +218,18 @@ type resultOperatorReader struct {
error *opendalError
}
+type opendalWriter struct{}
+
+type resultOperatorWriter struct {
+ writer *opendalWriter
+ error *opendalError
+}
+
+type resultWriterWrite struct {
+ size uint
+ error *opendalError
+}
+
type resultReaderRead struct {
size uint
error *opendalError
diff --git a/bindings/go/write.go b/bindings/go/write.go
index e1d18a1322..4b191dd8f3 100644
--- a/bindings/go/write.go
+++ b/bindings/go/write.go
@@ -21,6 +21,7 @@ package opendal
import (
"context"
+ "io"
"unsafe"
"github.com/jupiterrider/ffi"
@@ -98,6 +99,94 @@ func (op *Operator) CreateDir(path string) error {
return createDir(op.inner, path)
}
+// Writer returns a new Writer for the specified path.
+//
+// Writer is a wrapper around the C-binding function `opendal_operator_writer`.
+// It provides a way to obtain a writer for writing data to the storage system.
+//
+// # Parameters
+//
+// - path: The destination path where data will be written.
+//
+// # Returns
+//
+// - *Writer: A pointer to a Writer instance, or an error if the operation fails.
+//
+// # Example
+//
+// func exampleWriter(op *opendal.Operator) {
+// writer, err := op.Writer("test/")
+// if err != nil {
+// log.Fatal(err)
+// }
+// defer writer.Close()
+// _, err = writer.Write([]byte("Hello opendal writer!"))
+// if err != nil {
+// log.Fatal(err)
+// }
+// }
+//
+// Note: This example assumes proper error handling and import statements.
+func (op *Operator) Writer(path string) (*Writer, error) {
+ getWriter := getFFI[operatorWriter](op.ctx,
+ symOperatorWriter)
+ inner, err := getWriter(op.inner, path)
+ if err != nil {
+ return nil, err
+ }
+ writer := &Writer{
+ inner: inner,
+ ctx: op.ctx,
+ }
+ return writer, nil
+}
+
+type Writer struct {
+ inner *opendalWriter
+ ctx context.Context
+}
+
+// Write writes the given bytes to the specified path.
+//
+// Write is a wrapper around the C-binding function `opendal_operator_write`. It provides a simplified
+// interface for writing data to the storage. Write can be called multiple times to write
+// additional data to the same path.
+//
+// # Parameters
+//
+// - path: The destination path where the bytes will be written.
+// - data: The byte slice containing the data to be written.
+//
+// # Returns
+//
+// - error: An error if the write operation fails, or nil if successful.
+//
+// # Example
+//
+// func exampleWrite(op *opendal.Operator) {
+// err = op.Write("test", []byte("Hello opendal go binding!"))
+// if err != nil {
+// log.Fatal(err)
+// }
+// }
+//
+// Note: This example assumes proper error handling and import statements.
+func (w *Writer) Write(p []byte) (n int, err error) {
+ write := getFFI[writerWrite](w.ctx, symWriterWrite)
+ return write(w.inner, p)
+}
+
+// Close finishes the write and releases the resources associated with the Writer.
+// It is important to call Close after writing all the data to ensure that the data is
+// properly flushed and written to the storage.
+func (w *Writer) Close() error {
+ free := getFFI[writerFree](w.ctx, symWriterFree)
+ free(w.inner)
+ return nil
+}
+
+var _ io.WriteCloser = (*Writer)(nil)
+
const symOperatorWrite = "opendal_operator_write"
type operatorWrite func(op *opendalOperator, path string, data []byte) error
@@ -150,3 +239,76 @@ var withOperatorCreateDir = withFFI(ffiOpts{
return parseError(ctx, e)
}
})
+
+const symOperatorWriter = "opendal_operator_writer"
+
+type operatorWriter func(op *opendalOperator, path string) (*opendalWriter, error)
+
+var withOperatorWriter = withFFI(ffiOpts{
+ sym: symOperatorWriter,
+ rType: &ffi.TypePointer,
+ aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer},
+}, func(ctx context.Context, ffiCall func(rValue unsafe.Pointer, aValues ...unsafe.Pointer)) operatorWriter {
+ return func(op *opendalOperator, path string) (*opendalWriter, error) {
+ bytePath, err := unix.BytePtrFromString(path)
+ if err != nil {
+ return nil, err
+ }
+ var result resultOperatorWriter
+ ffiCall(
+ unsafe.Pointer(&result),
+ unsafe.Pointer(&op),
+ unsafe.Pointer(&bytePath),
+ )
+ if result.error != nil {
+ return nil, parseError(ctx, result.error)
+ }
+ return result.writer, nil
+ }
+})
+
+const symWriterFree = "opendal_writer_free"
+
+type writerFree func(w *opendalWriter)
+
+var withWriterFree = withFFI(ffiOpts{
+ sym: symWriterFree,
+ rType: &ffi.TypeVoid,
+ aTypes: []*ffi.Type{&ffi.TypePointer},
+}, func(ctx context.Context, ffiCall func(rValue unsafe.Pointer, aValues ...unsafe.Pointer)) writerFree {
+ return func(r *opendalWriter) {
+ ffiCall(
+ nil,
+ unsafe.Pointer(&r),
+ )
+ }
+})
+
+const symWriterWrite = "opendal_writer_write"
+
+type writerWrite func(r *opendalWriter, buf []byte) (size int, err error)
+
+var withWriterWrite = withFFI(ffiOpts{
+ sym: symWriterWrite,
+ rType: &typeResultWriterWrite,
+ aTypes: []*ffi.Type{&ffi.TypePointer, &ffi.TypePointer, &ffi.TypePointer},
+}, func(ctx context.Context, ffiCall func(rValue unsafe.Pointer, aValues ...unsafe.Pointer)) writerWrite {
+ return func(r *opendalWriter, buf []byte) (size int, err error) {
+ var length = len(buf)
+ if length == 0 {
+ return 0, nil
+ }
+ bytePtr := &buf[0]
+ var result resultWriterWrite
+ ffiCall(
+ unsafe.Pointer(&result),
+ unsafe.Pointer(&r),
+ unsafe.Pointer(&bytePtr),
+ unsafe.Pointer(&length),
+ )
+ if result.error != nil {
+ return 0, parseError(ctx, result.error)
+ }
+ return int(result.size), nil
+ }
+})