From bbc6e91b370686612076319545aa0568fb3ef738 Mon Sep 17 00:00:00 2001 From: Erik Unger Date: Thu, 7 Nov 2024 17:56:05 +0100 Subject: [PATCH] added error sentinels for JSON and XML marshalling/unmarshalling --- errors.go | 6 ++++++ file.go | 24 ++++++++++++++++++++---- memfile.go | 33 +++++++++++++++++++++++++++------ 3 files changed, 53 insertions(+), 10 deletions(-) diff --git a/errors.go b/errors.go index 88d048d..d86a77c 100644 --- a/errors.go +++ b/errors.go @@ -26,6 +26,12 @@ const ( // ErrFileSystemClosed is returned after a file system Close method was called ErrFileSystemClosed SentinelError = "file system is closed" + + ErrUnmarshalJSON SentinelError = "can't unmarshal JSON" + ErrMarshalJSON SentinelError = "can't marshal JSON" + + ErrUnmarshalXML SentinelError = "can't unmarshal XML" + ErrMarshalXML SentinelError = "can't marshal XML" ) /////////////////////////////////////////////////////////////////////////////// diff --git a/file.go b/file.go index f8062cb..ec1f688 100644 --- a/file.go +++ b/file.go @@ -1434,16 +1434,24 @@ func (file File) RemoveDirContentsContext(ctx context.Context, patterns ...strin } // ReadJSON reads and unmarshalles the JSON content of the file to output. +// +// Returns a wrapped ErrUnmarshalJSON when the unmarshalling failed. func (file File) ReadJSON(ctx context.Context, output any) error { data, err := file.ReadAllContext(ctx) if err != nil { return err } - return json.Unmarshal(data, output) + err = json.Unmarshal(data, output) + if err != nil { + return fmt.Errorf("%w because: %w", ErrUnmarshalJSON, err) + } + return nil } // WriteJSON mashalles input to JSON and writes it as the file. // Any indent arguments will be concanated and used as JSON line indentation. +// +// Returns a wrapped ErrMarshalJSON when the marshalling failed. func (file File) WriteJSON(ctx context.Context, input any, indent ...string) (err error) { if file == "" { return ErrEmptyPath @@ -1455,22 +1463,30 @@ func (file File) WriteJSON(ctx context.Context, input any, indent ...string) (er data, err = json.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return err + return fmt.Errorf("%w because: %w", ErrMarshalJSON, err) } return file.WriteAllContext(ctx, data) } // ReadXML reads and unmarshalles the XML content of the file to output. +// +// Returns a wrapped ErrUnmarshalXML when the unmarshalling failed. func (file File) ReadXML(ctx context.Context, output any) error { data, err := file.ReadAllContext(ctx) if err != nil { return err } - return xml.Unmarshal(data, output) + err = xml.Unmarshal(data, output) + if err != nil { + return fmt.Errorf("%w because: %w", ErrUnmarshalXML, err) + } + return nil } // WriteXML mashalles input to XML and writes it as the file. // Any indent arguments will be concanated and used as XML line indentation. +// +// Returns a wrapped ErrMarshalXML when the marshalling failed. func (file File) WriteXML(ctx context.Context, input any, indent ...string) (err error) { if file == "" { return ErrEmptyPath @@ -1482,7 +1498,7 @@ func (file File) WriteXML(ctx context.Context, input any, indent ...string) (err data, err = xml.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return err + return fmt.Errorf("%w because: %w", ErrMarshalXML, err) } data = append([]byte(xml.Header), data...) return file.WriteAllContext(ctx, data) diff --git a/memfile.go b/memfile.go index 0fe32ee..8eea130 100644 --- a/memfile.go +++ b/memfile.go @@ -62,6 +62,8 @@ func NewMemFile(name string, data []byte) MemFile { // NewMemFileWriteJSON returns a new MemFile with the input mashalled to JSON as FileData. // Any indent arguments will be concanated and used as JSON line indentation. +// +// Returns a wrapped ErrMarshalJSON when the marshalling failed. func NewMemFileWriteJSON(name string, input any, indent ...string) (MemFile, error) { var ( data []byte @@ -73,13 +75,15 @@ func NewMemFileWriteJSON(name string, input any, indent ...string) (MemFile, err data, err = json.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return MemFile{}, err + return MemFile{}, fmt.Errorf("%w because: %w", ErrMarshalJSON, err) } return MemFile{FileName: name, FileData: data}, nil } // NewMemFileWriteXML returns a new MemFile with the input mashalled to XML as FileData. // Any indent arguments will be concanated and used as XML line indentation. +// +// Returns a wrapped ErrMarshalXML when the marshalling failed. func NewMemFileWriteXML(name string, input any, indent ...string) (MemFile, error) { var ( data []byte @@ -91,7 +95,7 @@ func NewMemFileWriteXML(name string, input any, indent ...string) (MemFile, erro data, err = xml.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return MemFile{}, err + return MemFile{}, fmt.Errorf("%w because: %w", ErrMarshalXML, err) } return MemFile{FileName: name, FileData: append([]byte(xml.Header), data...)}, nil } @@ -286,16 +290,24 @@ func (f MemFile) OpenReadSeeker() (ReadSeekCloser, error) { } // ReadJSON reads and unmarshalles the JSON content of the file to output. +// +// Returns a wrapped ErrUnmarshalJSON when the unmarshalling failed. func (f MemFile) ReadJSON(ctx context.Context, output any) error { // Context is passed for identical call signature as other types if err := ctx.Err(); err != nil { return err } - return json.Unmarshal(f.FileData, output) + err := json.Unmarshal(f.FileData, output) + if err != nil { + return fmt.Errorf("%w because: %w", ErrUnmarshalJSON, err) + } + return nil } // WriteJSON mashalles input to JSON and writes it as the file. // Any indent arguments will be concanated and used as JSON line indentation. +// +// Returns a wrapped ErrMarshalJSON when the marshalling failed. func (f *MemFile) WriteJSON(ctx context.Context, input any, indent ...string) (err error) { // Context is passed for identical call signature as other types if err = ctx.Err(); err != nil { @@ -308,23 +320,31 @@ func (f *MemFile) WriteJSON(ctx context.Context, input any, indent ...string) (e data, err = json.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return err + return fmt.Errorf("%w because: %w", ErrMarshalJSON, err) } f.FileData = data return nil } // ReadXML reads and unmarshalles the XML content of the file to output. +// +// Returns a wrapped ErrUnmarshalXML when the unmarshalling failed. func (f MemFile) ReadXML(ctx context.Context, output any) error { // Context is passed for identical call signature as other types if err := ctx.Err(); err != nil { return err } - return xml.Unmarshal(f.FileData, output) + err := xml.Unmarshal(f.FileData, output) + if err != nil { + return fmt.Errorf("%w because: %w", ErrUnmarshalXML, err) + } + return nil } // WriteXML mashalles input to XML and writes it as the file. // Any indent arguments will be concanated and used as XML line indentation. +// +// Returns a wrapped ErrMarshalXML when the marshalling failed. func (f *MemFile) WriteXML(ctx context.Context, input any, indent ...string) (err error) { // Context is passed for identical call signature as other types if err = ctx.Err(); err != nil { @@ -337,7 +357,7 @@ func (f *MemFile) WriteXML(ctx context.Context, input any, indent ...string) (er data, err = xml.MarshalIndent(input, "", strings.Join(indent, "")) } if err != nil { - return err + return fmt.Errorf("%w because: %w", ErrMarshalXML, err) } f.FileData = append([]byte(xml.Header), data...) return nil @@ -346,6 +366,7 @@ func (f *MemFile) WriteXML(ctx context.Context, input any, indent ...string) (er // // MarshalJSON implements the json.Marshaler interface // func (f MemFile) MarshalJSON() ([]byte, error) { // encodedData := base64.RawURLEncoding.EncodeToString(f.FileData) +// // fmt.Errorf("%w because: %w", ErrMarshalJSON, err) // return json.Marshal(map[string]string{f.FileName: encodedData}) // }