go-hep.org/x/hep@v0.38.1/groot/rjson/rjson.go (about)

     1  // Copyright ©2023 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package rjson contains tools to marshal ROOT objects to JSON.
     6  package rjson // import "go-hep.org/x/hep/groot/rjson"
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/json"
    11  	"fmt"
    12  	"io"
    13  	"reflect"
    14  
    15  	"go-hep.org/x/hep/groot/rbytes"
    16  	"go-hep.org/x/hep/groot/root"
    17  )
    18  
    19  func Marshal(o root.Object) ([]byte, error) {
    20  	if o, ok := o.(rbytes.RSlicer); ok {
    21  		buf := new(bytes.Buffer)
    22  		enc := newEncoder(buf)
    23  		err := enc.Encode(o)
    24  		return buf.Bytes(), err
    25  	}
    26  
    27  	panic(fmt.Errorf("not implemented for %T", o))
    28  }
    29  
    30  type encoder struct {
    31  	w io.Writer
    32  }
    33  
    34  func newEncoder(w io.Writer) *encoder {
    35  	return &encoder{w: w}
    36  }
    37  
    38  func (enc *encoder) encode(v any) error {
    39  	if v, ok := v.(rbytes.RSlicer); ok {
    40  		return enc.Encode(v)
    41  	}
    42  
    43  	var (
    44  		err error
    45  		w   = enc.w
    46  		rv  = reflect.Indirect(reflect.ValueOf(v))
    47  	)
    48  
    49  	switch rv.Kind() {
    50  	case reflect.Slice:
    51  		_, err = w.Write([]byte("["))
    52  		if err != nil {
    53  			return err
    54  		}
    55  		for i := range rv.Len() {
    56  			if i > 0 {
    57  				_, err := w.Write([]byte(","))
    58  				if err != nil {
    59  					return err
    60  				}
    61  			}
    62  			err = enc.encode(rv.Index(i).Interface())
    63  			if err != nil {
    64  				return err
    65  			}
    66  		}
    67  		_, err = w.Write([]byte("]"))
    68  		if err != nil {
    69  			return err
    70  		}
    71  	default:
    72  		raw, err := json.Marshal(v)
    73  		if err != nil {
    74  			return err
    75  		}
    76  		_, err = w.Write(raw)
    77  		if err != nil {
    78  			return err
    79  		}
    80  	}
    81  
    82  	return nil
    83  }
    84  
    85  func (enc *encoder) Encode(v rbytes.RSlicer) error {
    86  	mbrs := v.RMembers()
    87  	name := v.(root.Object).Class()
    88  	w := enc.w
    89  	_, err := fmt.Fprintf(w, "{%q: %q", "_typename", name)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	for _, m := range mbrs {
    94  		_, err := fmt.Fprintf(w, ", %q: ", m.Name)
    95  		if err != nil {
    96  			return err
    97  		}
    98  		err = enc.encode(m.Value)
    99  		if err != nil {
   100  			return err
   101  		}
   102  	}
   103  	_, err = fmt.Fprintf(w, "}")
   104  	if err != nil {
   105  		return err
   106  	}
   107  	return nil
   108  }