mirror of
https://github.com/IBM/fp-go.git
synced 2025-08-10 22:31:32 +02:00
fix: add WithTempFile
Signed-off-by: Dr. Carsten Leue <carsten.leue@de.ibm.com>
This commit is contained in:
23
file/getters.go
Normal file
23
file/getters.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
|
||||||
|
package file
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// GetName is the getter for the `Name` property of [os.File]
|
||||||
|
func GetName(f *os.File) string {
|
||||||
|
return f.Name()
|
||||||
|
}
|
39
io/file/file.go
Normal file
39
io/file/file.go
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
|
||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Close closes a closeable resource and ignores a potential error
|
||||||
|
func Close[R io.Closer](r R) IO.IO[R] {
|
||||||
|
return IO.MakeIO[R](func() R {
|
||||||
|
r.Close() // #nosec: G104
|
||||||
|
return r
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes a resource and ignores a potential error
|
||||||
|
func Remove(name string) IO.IO[string] {
|
||||||
|
return IO.MakeIO[string](func() string {
|
||||||
|
os.Remove(name) // #nosec: G104
|
||||||
|
return name
|
||||||
|
})
|
||||||
|
}
|
@@ -21,6 +21,7 @@ import (
|
|||||||
IOE "github.com/IBM/fp-go/ioeither"
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// onClose closes a closeable resource
|
||||||
func onClose[R io.Closer](r R) IOE.IOEither[error, R] {
|
func onClose[R io.Closer](r R) IOE.IOEither[error, R] {
|
||||||
return IOE.TryCatchError(func() (R, error) {
|
return IOE.TryCatchError(func() (R, error) {
|
||||||
return r, r.Close()
|
return r, r.Close()
|
||||||
|
@@ -24,14 +24,24 @@ import (
|
|||||||
var (
|
var (
|
||||||
// Open opens a file for reading
|
// Open opens a file for reading
|
||||||
Open = IOE.Eitherize1(os.Open)
|
Open = IOE.Eitherize1(os.Open)
|
||||||
|
// Create opens a file for writing
|
||||||
|
Create = IOE.Eitherize1(os.Create)
|
||||||
// ReadFile reads the context of a file
|
// ReadFile reads the context of a file
|
||||||
ReadFile = IOE.Eitherize1(os.ReadFile)
|
ReadFile = IOE.Eitherize1(os.ReadFile)
|
||||||
// WriteFile writes a data blob to a file
|
|
||||||
WriteFile = func(dstName string, perm os.FileMode) func([]byte) IOE.IOEither[error, []byte] {
|
|
||||||
return func(data []byte) IOE.IOEither[error, []byte] {
|
|
||||||
return IOE.TryCatchError(func() ([]byte, error) {
|
|
||||||
return data, os.WriteFile(dstName, data, perm)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WriteFile writes a data blob to a file
|
||||||
|
func WriteFile(dstName string, perm os.FileMode) func([]byte) IOE.IOEither[error, []byte] {
|
||||||
|
return func(data []byte) IOE.IOEither[error, []byte] {
|
||||||
|
return IOE.TryCatchError(func() ([]byte, error) {
|
||||||
|
return data, os.WriteFile(dstName, data, perm)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove removes a file by name
|
||||||
|
func Remove(name string) IOE.IOEither[error, string] {
|
||||||
|
return IOE.TryCatchError(func() (string, error) {
|
||||||
|
return name, os.Remove(name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@@ -29,7 +29,7 @@ func onReadAll[R io.Reader](r R) IOE.IOEither[error, []byte] {
|
|||||||
|
|
||||||
// ReadAll uses a generator function to create a stream, reads it and closes it
|
// ReadAll uses a generator function to create a stream, reads it and closes it
|
||||||
func ReadAll[R io.ReadCloser](acquire IOE.IOEither[error, R]) IOE.IOEither[error, []byte] {
|
func ReadAll[R io.ReadCloser](acquire IOE.IOEither[error, R]) IOE.IOEither[error, []byte] {
|
||||||
return IOE.WithResource[error, R, []byte](
|
return IOE.WithResource[[]byte](
|
||||||
acquire,
|
acquire,
|
||||||
onClose[R])(
|
onClose[R])(
|
||||||
onReadAll[R],
|
onReadAll[R],
|
||||||
|
45
ioeither/file/tempfile.go
Normal file
45
ioeither/file/tempfile.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
|
||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
FL "github.com/IBM/fp-go/file"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
IO "github.com/IBM/fp-go/io"
|
||||||
|
IOF "github.com/IBM/fp-go/io/file"
|
||||||
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// CreateTemp created a temp file with proper parametrization
|
||||||
|
CreateTemp = IOE.Eitherize2(os.CreateTemp)
|
||||||
|
// onCreateTempFile creates a temp file with sensible defaults
|
||||||
|
onCreateTempFile = CreateTemp("", "*")
|
||||||
|
// destroy handler
|
||||||
|
onReleaseTempFile = F.Flow4(
|
||||||
|
IOF.Close[*os.File],
|
||||||
|
IO.Map(FL.GetName),
|
||||||
|
IOE.FromIO[error, string],
|
||||||
|
IOE.Chain(Remove),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithTempFile creates a temporary file, then invokes a callback to create a resource based on the file, then close and remove the temp file
|
||||||
|
func WithTempFile[A any](f func(*os.File) IOE.IOEither[error, A]) IOE.IOEither[error, A] {
|
||||||
|
return IOE.WithResource[A](onCreateTempFile, onReleaseTempFile)(f)
|
||||||
|
}
|
46
ioeither/file/tempfile_test.go
Normal file
46
ioeither/file/tempfile_test.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2023 IBM Corp.
|
||||||
|
// All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed 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.
|
||||||
|
|
||||||
|
package file
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
E "github.com/IBM/fp-go/either"
|
||||||
|
F "github.com/IBM/fp-go/function"
|
||||||
|
IOE "github.com/IBM/fp-go/ioeither"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWithTempFile(t *testing.T) {
|
||||||
|
|
||||||
|
res := WithTempFile(onWriteAll[*os.File]([]byte("Carsten")))
|
||||||
|
|
||||||
|
assert.Equal(t, E.Of[error]([]byte("Carsten")), res())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithTempFileOnClosedFile(t *testing.T) {
|
||||||
|
|
||||||
|
res := WithTempFile(func(f *os.File) IOE.IOEither[error, []byte] {
|
||||||
|
return F.Pipe2(
|
||||||
|
f,
|
||||||
|
onWriteAll[*os.File]([]byte("Carsten")),
|
||||||
|
IOE.ChainFirst(F.Constant1[[]byte](onClose(f))),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, E.Of[error]([]byte("Carsten")), res())
|
||||||
|
}
|
@@ -34,7 +34,7 @@ func onWriteAll[W io.Writer](data []byte) func(w W) IOE.IOEither[error, []byte]
|
|||||||
func WriteAll[W io.WriteCloser](data []byte) func(acquire IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
func WriteAll[W io.WriteCloser](data []byte) func(acquire IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
||||||
onWrite := onWriteAll[W](data)
|
onWrite := onWriteAll[W](data)
|
||||||
return func(onCreate IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
return func(onCreate IOE.IOEither[error, W]) IOE.IOEither[error, []byte] {
|
||||||
return IOE.WithResource[error, W, []byte](
|
return IOE.WithResource[[]byte](
|
||||||
onCreate,
|
onCreate,
|
||||||
onClose[W])(
|
onClose[W])(
|
||||||
onWrite,
|
onWrite,
|
||||||
@@ -43,8 +43,8 @@ func WriteAll[W io.WriteCloser](data []byte) func(acquire IOE.IOEither[error, W]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write uses a generator function to create a stream, writes data to it and closes it
|
// Write uses a generator function to create a stream, writes data to it and closes it
|
||||||
func Write[W io.WriteCloser, R any](acquire IOE.IOEither[error, W]) func(use func(W) IOE.IOEither[error, R]) IOE.IOEither[error, R] {
|
func Write[R any, W io.WriteCloser](acquire IOE.IOEither[error, W]) func(use func(W) IOE.IOEither[error, R]) IOE.IOEither[error, R] {
|
||||||
return IOE.WithResource[error, W, R](
|
return IOE.WithResource[R](
|
||||||
acquire,
|
acquire,
|
||||||
onClose[W])
|
onClose[W])
|
||||||
}
|
}
|
||||||
|
@@ -192,7 +192,7 @@ func ChainFirstIOK[E, A, B any](f func(A) I.IO[B]) func(IOEither[E, A]) IOEither
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
// WithResource constructs a function that creates a resource, then operates on it and then releases the resource
|
||||||
func WithResource[E, R, A, ANY any](onCreate IOEither[E, R], onRelease func(R) IOEither[E, ANY]) func(func(R) IOEither[E, A]) IOEither[E, A] {
|
func WithResource[A, E, R, ANY any](onCreate IOEither[E, R], onRelease func(R) IOEither[E, ANY]) func(func(R) IOEither[E, A]) IOEither[E, A] {
|
||||||
return G.WithResource[IOEither[E, A]](onCreate, onRelease)
|
return G.WithResource[IOEither[E, A]](onCreate, onRelease)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user