github.com/kaydxh/golang@v0.0.131/go/reflect/truncate.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package reflect
    23  
    24  import (
    25  	"bytes"
    26  	"fmt"
    27  	"reflect"
    28  )
    29  
    30  func TruncateBytes(v interface{}) interface{} {
    31  	return Truncate(v, func(v interface{}) bool {
    32  		_, ok := v.([]byte)
    33  		return ok
    34  	})
    35  
    36  }
    37  
    38  func Truncate(v interface{}, f func(v interface{}) bool) interface{} {
    39  	truncate(reflect.ValueOf(v), f)
    40  	return v
    41  
    42  }
    43  
    44  //https://stackoverflow.com/questions/6395076/using-reflect-how-do-you-set-the-value-of-a-struct-field
    45  // truncate []byte, [][]byte, not support others, eg: [][][]byte
    46  // struct must use pointer of sturct, or not rewrite it
    47  func truncate(v reflect.Value, f func(v interface{}) bool) {
    48  	if !v.IsValid() {
    49  		return
    50  	}
    51  
    52  	if v.Type() == nil {
    53  		return
    54  	}
    55  
    56  	if v.CanInterface() {
    57  		vv := v.Interface()
    58  		if f(vv) {
    59  			truncateToLen(v)
    60  		}
    61  	}
    62  
    63  	switch v.Kind() {
    64  	case reflect.Struct:
    65  		for i := 0; i < v.NumField(); i++ {
    66  			truncate(v.Field(i), f)
    67  		}
    68  
    69  	case reflect.Array, reflect.Slice:
    70  		for i := 0; i < v.Len(); i++ {
    71  			truncate(v.Index(i), f)
    72  		}
    73  
    74  	case reflect.Ptr:
    75  		truncate(reflect.Indirect(v), f)
    76  
    77  	default:
    78  
    79  	}
    80  
    81  	return
    82  
    83  }
    84  
    85  func truncateToLen(oldValue reflect.Value) {
    86  	if !oldValue.IsValid() {
    87  		return
    88  	}
    89  	if !oldValue.CanInterface() {
    90  		return
    91  	}
    92  
    93  	vv := oldValue.Interface()
    94  	switch vv := vv.(type) {
    95  	case []byte:
    96  		writeLenToReflectValue(oldValue, len(vv))
    97  	}
    98  
    99  	return
   100  }
   101  
   102  func writeLenToReflectValue(v reflect.Value, length int) interface{} {
   103  	// if v can not set, return truncate result
   104  	if !v.CanAddr() {
   105  		return fmt.Sprintf("bytes len: %v", length)
   106  	}
   107  
   108  	var buf bytes.Buffer
   109  	buf.WriteString(fmt.Sprintf("bytes len: %v", length))
   110  	v.SetBytes(buf.Bytes())
   111  	return v
   112  }