Skip to content

Commit

Permalink
added error sentinels for JSON and XML marshalling/unmarshalling
Browse files Browse the repository at this point in the history
  • Loading branch information
ungerik committed Nov 7, 2024
1 parent a6e3fe8 commit bbc6e91
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
6 changes: 6 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

///////////////////////////////////////////////////////////////////////////////
Expand Down
24 changes: 20 additions & 4 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down
33 changes: 27 additions & 6 deletions memfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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
Expand All @@ -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})
// }

Expand Down

0 comments on commit bbc6e91

Please sign in to comment.