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

     1  # `lang.ArrayWithTypeTemplate()` (template API)
     2  
     3  > Unmarshals a data type into a Go struct and returns the results as an array with data type included
     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 `ReadArrayWithType()` functions.
    12  
    13  Because `lang.ArrayTemplateWithType()` 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/lang/types"
    56  	"github.com/lmorg/murex/utils"
    57  	"github.com/lmorg/murex/utils/consts"
    58  )
    59  
    60  // ArrayWithTypeTemplate is a template function for reading arrays from marshalled data
    61  func ArrayWithTypeTemplate(ctx context.Context, dataType string, marshal func(interface{}) ([]byte, error), unmarshal func([]byte, interface{}) error, read stdio.Io, callback func(interface{}, string)) error {
    62  	b, err := read.ReadAll()
    63  	if err != nil {
    64  		return err
    65  	}
    66  
    67  	if len(utils.CrLfTrim(b)) == 0 {
    68  		return nil
    69  	}
    70  
    71  	var v interface{}
    72  	err = unmarshal(b, &v)
    73  
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	switch v := v.(type) {
    79  	case []interface{}:
    80  		return readArrayWithTypeBySliceInterface(ctx, dataType, marshal, v, callback)
    81  
    82  	case []string:
    83  		return readArrayWithTypeBySliceString(ctx, v, callback)
    84  
    85  	case []float64:
    86  		return readArrayWithTypeBySliceFloat(ctx, v, callback)
    87  
    88  	case []int:
    89  		return readArrayWithTypeBySliceInt(ctx, v, callback)
    90  
    91  	case []bool:
    92  		return readArrayWithTypeBySliceBool(ctx, v, callback)
    93  
    94  	case string:
    95  		return readArrayWithTypeByString(v, callback)
    96  
    97  	case []byte:
    98  		return readArrayWithTypeByString(string(v), callback)
    99  
   100  	case []rune:
   101  		return readArrayWithTypeByString(string(v), callback)
   102  
   103  	case map[string]string:
   104  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   105  
   106  	case map[string]interface{}:
   107  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   108  
   109  	case map[interface{}]string:
   110  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   111  
   112  	case map[interface{}]interface{}:
   113  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   114  
   115  	case map[int]string:
   116  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   117  
   118  	case map[int]interface{}:
   119  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   120  
   121  	case map[float64]string:
   122  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   123  
   124  	case map[float64]interface{}:
   125  		return readArrayWithTypeByMap(ctx, dataType, marshal, v, callback)
   126  
   127  	default:
   128  		return fmt.Errorf("cannot turn %T into an array\n%s", v, consts.IssueTrackerURL)
   129  	}
   130  }
   131  
   132  func readArrayWithTypeByString(v string, callback func(interface{}, string)) error {
   133  	callback(v, types.String)
   134  
   135  	return nil
   136  }
   137  
   138  func readArrayWithTypeBySliceInt(ctx context.Context, v []int, callback func(interface{}, string)) error {
   139  	for i := range v {
   140  		select {
   141  		case <-ctx.Done():
   142  			return nil
   143  
   144  		default:
   145  			callback(v[i], types.Integer)
   146  		}
   147  	}
   148  
   149  	return nil
   150  }
   151  
   152  func readArrayWithTypeBySliceFloat(ctx context.Context, v []float64, callback func(interface{}, string)) error {
   153  	for i := range v {
   154  		select {
   155  		case <-ctx.Done():
   156  			return nil
   157  
   158  		default:
   159  			callback(v[i], types.Number)
   160  		}
   161  	}
   162  
   163  	return nil
   164  }
   165  
   166  func readArrayWithTypeBySliceBool(ctx context.Context, v []bool, callback func(interface{}, string)) error {
   167  	for i := range v {
   168  		select {
   169  		case <-ctx.Done():
   170  			return nil
   171  
   172  		default:
   173  			callback(v[i], types.Boolean)
   174  
   175  		}
   176  	}
   177  
   178  	return nil
   179  }
   180  
   181  func readArrayWithTypeBySliceString(ctx context.Context, v []string, callback func(interface{}, string)) error {
   182  	for i := range v {
   183  		select {
   184  		case <-ctx.Done():
   185  			return nil
   186  
   187  		default:
   188  			callback(v[i], types.String)
   189  		}
   190  	}
   191  
   192  	return nil
   193  }
   194  
   195  func readArrayWithTypeBySliceInterface(ctx context.Context, dataType string, marshal func(interface{}) ([]byte, error), v []interface{}, callback func(interface{}, string)) error {
   196  	if len(v) == 0 {
   197  		return nil
   198  	}
   199  
   200  	for i := range v {
   201  		select {
   202  		case <-ctx.Done():
   203  			return nil
   204  
   205  		default:
   206  			switch v[i].(type) {
   207  
   208  			case string:
   209  				callback((v[i].(string)), types.String)
   210  
   211  			case float64:
   212  				callback(v[i].(float64), types.Number)
   213  
   214  			case int:
   215  				callback(v[i].(int), types.Integer)
   216  
   217  			case bool:
   218  				if v[i].(bool) {
   219  					callback(true, types.Boolean)
   220  				} else {
   221  					callback(false, types.Boolean)
   222  				}
   223  
   224  			case []byte:
   225  				callback(string(v[i].([]byte)), types.String)
   226  
   227  			case []rune:
   228  				callback(string(v[i].([]rune)), types.String)
   229  
   230  			case nil:
   231  				callback(nil, types.Null)
   232  
   233  			default:
   234  				jBytes, err := marshal(v[i])
   235  				if err != nil {
   236  					return err
   237  				}
   238  				callback(jBytes, dataType)
   239  			}
   240  		}
   241  	}
   242  
   243  	return nil
   244  }
   245  
   246  func readArrayWithTypeByMap[K comparable, V any](ctx context.Context, dataType string, marshal func(interface{}) ([]byte, error), v map[K]V, callback func(interface{}, string)) error {
   247  	for key, val := range v {
   248  		select {
   249  		case <-ctx.Done():
   250  			return nil
   251  		default:
   252  			m := map[K]any{key: val}
   253  			b, err := marshal(m)
   254  			if err != nil {
   255  				return err
   256  			}
   257  			callback(string(b), dataType)
   258  		}
   259  	}
   260  
   261  	return nil
   262  }
   263  ```
   264  
   265  ## Parameters
   266  
   267  1. `func(interface{}) ([]byte, error)`: data type's marshaller
   268  2. `func([]byte, interface{}) error`: data type's unmarshaller
   269  3. `stdio.Io`: stream to read from (eg STDIN)
   270  4. `func(interface{}, string)`: callback function to write each array element, with data type
   271  
   272  ## See Also
   273  
   274  * [apis/`ReadArray()` (type)](../apis/ReadArray.md):
   275    Read from a data type one array element at a time
   276  * [apis/`ReadArrayWithType()` (type)](../apis/ReadArrayWithType.md):
   277    Read from a data type one array element at a time and return the elements contents and data type
   278  * [apis/`ReadIndex()` (type)](../apis/ReadIndex.md):
   279    Data type handler for the index, `[`, builtin
   280  * [apis/`ReadMap()` (type)](../apis/ReadMap.md):
   281    Treat data type as a key/value structure and read its contents
   282  * [apis/`ReadNotIndex()` (type)](../apis/ReadNotIndex.md):
   283    Data type handler for the bang-prefixed index, `![`, builtin
   284  * [apis/`WriteArray()` (type)](../apis/WriteArray.md):
   285    Write a data type, one array element at a time
   286  * [apis/`lang.IndexTemplateObject()` (template API)](../apis/lang.IndexTemplateObject.md):
   287    Returns element(s) from a data structure
   288  * [apis/`lang.IndexTemplateTable()` (template API)](../apis/lang.IndexTemplateTable.md):
   289    Returns element(s) from a table
   290  
   291  <hr/>
   292  
   293  This document was generated from [lang/stdio/interface_doc.yaml](https://github.com/lmorg/murex/blob/master/lang/stdio/interface_doc.yaml).