From b15ab38861fa90a4bb6872141a76d91b3885ce7e Mon Sep 17 00:00:00 2001 From: "Dr. Carsten Leue" Date: Tue, 19 Sep 2023 18:06:32 +0200 Subject: [PATCH] fix: add WithTempFile to ReaderIOEither Signed-off-by: Dr. Carsten Leue --- context/readerioeither/file/file.go | 7 ++++ context/readerioeither/file/tempfile.go | 53 ++++++++++++++++++++++++ context/readerioeither/generic/reader.go | 22 ++++++++++ context/readerioeither/reader.go | 8 ++++ either/exec/exec.go | 2 +- exec/exec.go | 5 ++- 6 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 context/readerioeither/file/tempfile.go diff --git a/context/readerioeither/file/file.go b/context/readerioeither/file/file.go index d54507a..a3422ad 100644 --- a/context/readerioeither/file/file.go +++ b/context/readerioeither/file/file.go @@ -25,6 +25,7 @@ import ( F "github.com/IBM/fp-go/function" "github.com/IBM/fp-go/internal/file" IOE "github.com/IBM/fp-go/ioeither" + IOEF "github.com/IBM/fp-go/ioeither/file" ) var ( @@ -35,6 +36,12 @@ var ( RIOE.FromIOEither[*os.File], RIOE.WithContext[*os.File], ) + + // Remove removes a file by name + Remove = F.Flow2( + IOEF.Remove, + RIOE.FromIOEither[string], + ) ) // Close closes an object diff --git a/context/readerioeither/file/tempfile.go b/context/readerioeither/file/tempfile.go new file mode 100644 index 0000000..20be139 --- /dev/null +++ b/context/readerioeither/file/tempfile.go @@ -0,0 +1,53 @@ +// 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" + + RIOE "github.com/IBM/fp-go/context/readerioeither" + 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" + IOEF "github.com/IBM/fp-go/ioeither/file" +) + +var ( + // onCreateTempFile creates a temp file with sensible defaults + onCreateTempFile = CreateTemp("", "*") + // destroy handler + onReleaseTempFile = F.Flow4( + IOF.Close[*os.File], + IO.Map(FL.GetName), + RIOE.FromIO[string], + RIOE.Chain(Remove), + ) +) + +// CreateTemp created a temp file with proper parametrization +func CreateTemp(dir, pattern string) RIOE.ReaderIOEither[*os.File] { + return F.Pipe2( + IOEF.CreateTemp(dir, pattern), + RIOE.FromIOEither[*os.File], + RIOE.WithContext[*os.File], + ) +} + +// 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) RIOE.ReaderIOEither[A]) RIOE.ReaderIOEither[A] { + return RIOE.WithResource[A](onCreateTempFile, onReleaseTempFile)(f) +} diff --git a/context/readerioeither/generic/reader.go b/context/readerioeither/generic/reader.go index a74fac8..415cfd8 100644 --- a/context/readerioeither/generic/reader.go +++ b/context/readerioeither/generic/reader.go @@ -100,6 +100,28 @@ func Map[ return RIE.Map[GRA, GRB](f) } +func MonadMapTo[ + GRA ~func(context.Context) GIOA, + GRB ~func(context.Context) GIOB, + + GIOA ~func() E.Either[error, A], + GIOB ~func() E.Either[error, B], + + A, B any](fa GRA, b B) GRB { + return RIE.MonadMapTo[GRA, GRB](fa, b) +} + +func MapTo[ + GRA ~func(context.Context) GIOA, + GRB ~func(context.Context) GIOB, + + GIOA ~func() E.Either[error, A], + GIOB ~func() E.Either[error, B], + + A, B any](b B) func(GRA) GRB { + return RIE.MapTo[GRA, GRB](b) +} + func MonadChain[ GRA ~func(context.Context) GIOA, GRB ~func(context.Context) GIOB, diff --git a/context/readerioeither/reader.go b/context/readerioeither/reader.go index 0205d1c..04298f2 100644 --- a/context/readerioeither/reader.go +++ b/context/readerioeither/reader.go @@ -61,6 +61,14 @@ func Map[A, B any](f func(A) B) func(ReaderIOEither[A]) ReaderIOEither[B] { return G.Map[ReaderIOEither[A], ReaderIOEither[B]](f) } +func MonadMapTo[A, B any](fa ReaderIOEither[A], b B) ReaderIOEither[B] { + return G.MonadMapTo[ReaderIOEither[A], ReaderIOEither[B]](fa, b) +} + +func MapTo[A, B any](b B) func(ReaderIOEither[A]) ReaderIOEither[B] { + return G.MapTo[ReaderIOEither[A], ReaderIOEither[B]](b) +} + func MonadChain[A, B any](ma ReaderIOEither[A], f func(A) ReaderIOEither[B]) ReaderIOEither[B] { return G.MonadChain(ma, f) } diff --git a/either/exec/exec.go b/either/exec/exec.go index a244e50..5056334 100644 --- a/either/exec/exec.go +++ b/either/exec/exec.go @@ -27,7 +27,7 @@ import ( var ( // Command executes a command // use this version if the command does not produce any side effect, i.e. if the output is uniquely determined by by the input - // typically you'd rather use the IOEither version of the command + // typically you'd rather use the [IOEither] version of the command Command = F.Curry3(command) ) diff --git a/exec/exec.go b/exec/exec.go index 7d86243..ba4b4ae 100644 --- a/exec/exec.go +++ b/exec/exec.go @@ -20,11 +20,14 @@ import ( ) type ( - // command output + // CommandOutput represents the output of executing a command. The first field in the [Tuple2] is + // stdout, the second one is stderr. Use [StdOut] and [StdErr] to access these fields CommandOutput = T.Tuple2[[]byte, []byte] ) var ( + // StdOut returns the field of a [CommandOutput] representing `stdout` StdOut = T.First[[]byte, []byte] + // StdErr returns the field of a [CommandOutput] representing `stderr` StdErr = T.Second[[]byte, []byte] )