github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/docs/apis/lang.ArrayTemplate.md (about)

     1  # `lang.ArrayTemplate()` (template API)
     2  
     3  > Unmarshals a data type into a Go struct and returns the results as an array
     4  
     5  ## Description
     6  
     7  This is a template API you can use for your custom data types to wrap around an
     8  existing Go marshaller and return a Murex array which is consistent with
     9  other structures such as nested JSON or YAML documents.
    10  
    11  It should only be called from `ReadArray()` functions.
    12  
    13  Because `lang.ArrayTemplate()` relies on a marshaller, it means any types that
    14  rely on this API are not going to be stream-able.
    15  
    16  
    17  
    18  ## Examples
    19  
    20  Example calling `lang.ArrayTemplate()` function:
    21  
    22  ```go
    23  package json
    24  
    25  import (
    26  	"context"
    27  
    28  	"github.com/lmorg/murex/lang"
    29  	"github.com/lmorg/murex/lang/stdio"
    30  	"github.com/lmorg/murex/utils/json"
    31  )
    32  
    33  func readArray(ctx context.Context, read stdio.Io, callback func([]byte)) error {
    34  	// Create a marshaller function to pass to ArrayTemplate
    35  	marshaller := func(v interface{}) ([]byte, error) {
    36  		return json.Marshal(v, read.IsTTY())
    37  	}
    38  
    39  	return lang.ArrayTemplate(ctx, marshaller, json.Unmarshal, read, callback)
    40  }
    41  ```
    42  
    43  ## Detail
    44  
    45  ### API Source:
    46  
    47  ```go
    48  package lang
    49  
    50  import (
    51  	"context"
    52  	"fmt"
    53  
    54  	"github.com/lmorg/murex/lang/stdio"
    55  	"github.com/lmorg/murex/utils"
    56  )
    57  
    58  // ArrayTemplate is a template function for reading arrays from marshalled data
    59  func ArrayTemplate(ctx context.Context, marshal func(interface{}) ([]byte, error), unmarshal func([]byte, interface{}) error, read stdio.Io, callback func([]byte)) error {
    60  	b, err := read.ReadAll()
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	if len(utils.CrLfTrim(b)) == 0 {
    66  		return nil
    67  	}
    68  
    69  	var v interface{}
    70  	err = unmarshal(b, &v)
    71  
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	switch v := v.(type) {
    77  	case string:
    78  		return readArrayByString(v, callback)
    79  
    80  	case []string:
    81  		return readArrayBySliceString(ctx, v, callback)
    82  
    83  	case []interface{}:
    84  		return readArrayBySliceInterface(ctx, marshal, v, callback)
    85  
    86  	case map[string]string:
    87  		return readArrayByMapStrStr(ctx, v, callback)
    88  
    89  	case map[string]interface{}:
    90  		return readArrayByMapStrIface(ctx, marshal, v, callback)
    91  
    92  	case map[interface{}]string:
    93  		return readArrayByMapIfaceStr(ctx, v, callback)
    94  
    95  	case map[interface{}]interface{}:
    96  		return readArrayByMapIfaceIface(ctx, marshal, v, callback)
    97  
    98  	default:
    99  		jBytes, err := marshal(v)
   100  		if err != nil {
   101  
   102  			return err
   103  		}
   104  
   105  		callback(jBytes)
   106  
   107  		return nil
   108  	}
   109  }
   110  
   111  func readArrayByString(v string, callback func([]byte)) error {
   112  	callback([]byte(v))
   113  
   114  	return nil
   115  }
   116  
   117  func readArrayBySliceString(ctx context.Context, v []string, callback func([]byte)) error {
   118  	for i := range v {
   119  		select {
   120  		case <-ctx.Done():
   121  			return nil
   122  
   123  		default:
   124  			callback([]byte(v[i]))
   125  		}
   126  	}
   127  
   128  	return nil
   129  }
   130  
   131  func readArrayBySliceInterface(ctx context.Context, marshal func(interface{}) ([]byte, error), v []interface{}, callback func([]byte)) error {
   132  	if len(v) == 0 {
   133  		return nil
   134  	}
   135  
   136  	for i := range v {
   137  		select {
   138  		case <-ctx.Done():
   139  			return nil
   140  
   141  		default:
   142  			switch v := v[i].(type) {
   143  			case string:
   144  				callback([]byte(v))
   145  
   146  			case []byte:
   147  				callback(v)
   148  
   149  			default:
   150  				jBytes, err := marshal(v)
   151  				if err != nil {
   152  					return err
   153  				}
   154  				callback(jBytes)
   155  			}
   156  		}
   157  	}
   158  
   159  	return nil
   160  }
   161  
   162  func readArrayByMapIfaceIface(ctx context.Context, marshal func(interface{}) ([]byte, error), v map[interface{}]interface{}, callback func([]byte)) error {
   163  	for key, val := range v {
   164  		select {
   165  		case <-ctx.Done():
   166  			return nil
   167  
   168  		default:
   169  			bKey := []byte(fmt.Sprint(key) + ": ")
   170  			b, err := marshal(val)
   171  			if err != nil {
   172  				return err
   173  			}
   174  			callback(append(bKey, b...))
   175  		}
   176  	}
   177  
   178  	return nil
   179  }
   180  
   181  func readArrayByMapStrStr(ctx context.Context, v map[string]string, callback func([]byte)) error {
   182  	for key, val := range v {
   183  		select {
   184  		case <-ctx.Done():
   185  			return nil
   186  
   187  		default:
   188  			callback([]byte(key + ": " + val))
   189  		}
   190  	}
   191  
   192  	return nil
   193  }
   194  
   195  func readArrayByMapStrIface(ctx context.Context, marshal func(interface{}) ([]byte, error), v map[string]interface{}, callback func([]byte)) error {
   196  	for key, val := range v {
   197  		select {
   198  		case <-ctx.Done():
   199  			return nil
   200  
   201  		default:
   202  			bKey := []byte(key + ": ")
   203  			b, err := marshal(val)
   204  			if err != nil {
   205  				return err
   206  			}
   207  			callback(append(bKey, b...))
   208  		}
   209  	}
   210  
   211  	return nil
   212  }
   213  
   214  func readArrayByMapIfaceStr(ctx context.Context, v map[interface{}]string, callback func([]byte)) error {
   215  	for key, val := range v {
   216  		select {
   217  		case <-ctx.Done():
   218  			return nil
   219  
   220  		default:
   221  			callback([]byte(fmt.Sprint(key) + ": " + val))
   222  		}
   223  	}
   224  
   225  	return nil
   226  }
   227  ```
   228  
   229  ## Parameters
   230  
   231  1. `func(interface{}) ([]byte, error)`: data type's marshaller
   232  2. `func([]byte, interface{}) error`: data type's unmarshaller
   233  3. `stdio.Io`: stream to read from (eg STDIN)
   234  4. `func([]byte)`: callback function to write each array element
   235  
   236  ## See Also
   237  
   238  * [apis/`ReadArray()` (type)](../apis/ReadArray.md):
   239    Read from a data type one array element at a time
   240  * [apis/`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md):
   241    Read from a data type one array element at a time and return the elements contents and data type
   242  * [apis/`ReadIndex()` (type)](../apis/ReadIndex.md):
   243    Data type handler for the index, `[`, builtin
   244  * [apis/`ReadMap()` (type)](../apis/ReadMap.md):
   245    Treat data type as a key/value structure and read its contents
   246  * [apis/`ReadNotIndex()` (type)](../apis/ReadNotIndex.md):
   247    Data type handler for the bang-prefixed index, `![`, builtin
   248  * [apis/`WriteArray()` (type)](../apis/WriteArray.md):
   249    Write a data type, one array element at a time
   250  * [apis/`lang.IndexTemplateObject()` (template API)](../apis/lang.IndexTemplateObject.md):
   251    Returns element(s) from a data structure
   252  * [apis/`lang.IndexTemplateTable()` (template API)](../apis/lang.IndexTemplateTable.md):
   253    Returns element(s) from a table
   254  
   255  <hr/>
   256  
   257  This document was generated from [lang/stdio/interface_doc.yaml](https://github.com/lmorg/murex/blob/master/lang/stdio/interface_doc.yaml).