github.com/pavlo67/common@v0.5.3/common/serialization/jlist.go (about)

     1  package serialization
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"regexp"
     9  
    10  	"github.com/pavlo67/common/common/errors"
    11  	"github.com/pavlo67/common/common/filelib"
    12  )
    13  
    14  const onJSONList = "on serialization.JSONList()"
    15  
    16  func JSONList[T any](list []T, prefix, indent string) ([]byte, error) {
    17  	prefixBytes, indentBytes := []byte(prefix), []byte(indent)
    18  
    19  	jsonBytes := []byte{'[', '\n'}
    20  
    21  	for i, item := range list {
    22  		itemBytes, err := json.Marshal(item)
    23  		if err != nil {
    24  			return nil, errors.Wrap(err, onJSONList)
    25  		}
    26  
    27  		if i > 0 {
    28  			jsonBytes = append(append(jsonBytes, ','), prefixBytes...)
    29  		}
    30  		jsonBytes = append(append(jsonBytes, indentBytes...), itemBytes...)
    31  	}
    32  
    33  	return append(jsonBytes, '\n', ']'), nil
    34  }
    35  
    36  const onSavePart = "on serialization.SavePart()"
    37  
    38  func SavePart(data interface{}, marshaler Marshaler, filename string) error {
    39  
    40  	logData, err := marshaler.Marshal(data)
    41  	if err != nil {
    42  		return errors.Wrap(err, onSavePart)
    43  	} else if err = filelib.AppendFile(filename, append(logData, '\n')); err != nil {
    44  		return errors.Wrap(err, onSavePart)
    45  	}
    46  
    47  	return nil
    48  }
    49  
    50  const onReadPart = "on serialization.ReadPart()"
    51  
    52  func ReadPart(filename string, n int, marshaler Marshaler, data interface{}) error {
    53  	dataBytes, err := os.ReadFile(filename)
    54  	if err != nil {
    55  		return fmt.Errorf("reading %s got: %s / "+onReadPart, filename, err)
    56  	}
    57  	lines := bytes.Split(dataBytes, []byte{'\n'})
    58  	if n < 0 || n >= len(lines) {
    59  		return fmt.Errorf("wrong n (%d) to get from %d lines / "+onReadPart, n, len(lines))
    60  	}
    61  
    62  	if err := marshaler.Unmarshal(lines[n], data); err != nil {
    63  		return fmt.Errorf("unmarshaling %s got: %s / "+onReadPart, dataBytes, err)
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  var reEmptyLine = regexp.MustCompile(`^\s*$`)
    70  
    71  const onReadAllPartsJSON = "on serialization.ReadAllPartsJSON()"
    72  
    73  func ReadAllPartsJSON(filename string, data interface{}) error {
    74  	exists, isDir := filelib.FileExistsAny(filename)
    75  	if !exists {
    76  		return nil
    77  	} else if isDir {
    78  		return fmt.Errorf("%s is a directory / "+onReadAllPartsJSON, filename)
    79  	}
    80  
    81  	dataBytesRaw, err := os.ReadFile(filename)
    82  	if err != nil {
    83  		return fmt.Errorf("reading %s got: %s / "+onReadAllPartsJSON, filename, err)
    84  	}
    85  	var lines [][]byte
    86  	for _, line := range bytes.Split(dataBytesRaw, []byte{'\n'}) {
    87  		if !reEmptyLine.Match(line) {
    88  			lines = append(lines, line)
    89  		}
    90  	}
    91  
    92  	dataBytesLines := bytes.Join(lines, []byte{','})
    93  	dataBytes := append([]byte{'['}, append(dataBytesLines, ']')...)
    94  
    95  	if err := json.Unmarshal(dataBytes, data); err != nil {
    96  		return fmt.Errorf("unmarshaling %s got: %s / "+onReadAllPartsJSON, dataBytes, err)
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  const onSaveAllPartsJSON = "on serialization.SaveAllPartsJSON()"
   103  
   104  func SaveAllPartsJSON[T any](data []T, filename string) error {
   105  	var dataBytes []byte
   106  
   107  	for _, item := range data {
   108  		itemBytes, err := json.Marshal(item)
   109  		if err != nil {
   110  			return fmt.Errorf("marshaling %v got: %s / "+onSaveAllPartsJSON, item, err)
   111  		}
   112  
   113  		dataBytes = append(dataBytes, itemBytes...)
   114  		dataBytes = append(dataBytes, '\n')
   115  	}
   116  
   117  	err := os.WriteFile(filename, dataBytes, 0644)
   118  	if err != nil {
   119  		return errors.Wrap(err, onSaveAllPartsJSON)
   120  	}
   121  
   122  	return nil
   123  }