github.com/GuanceCloud/cliutils@v1.1.21/point/encode_v2.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the MIT License.
     3  // This product includes software developed at Guance Cloud (https://www.guance.com/).
     4  // Copyright 2021-present Guance, Inc.
     5  
     6  package point
     7  
     8  // EncodeV2 set points to be encoded.
     9  func (e *Encoder) EncodeV2(pts []*Point) {
    10  	e.pts = pts
    11  }
    12  
    13  // Next is a iterator that return encoded data in prepared buf.
    14  // If all points encoded done, return false.
    15  // If any error occurred, we can get the error by call e.LastErr().
    16  func (e *Encoder) Next(buf []byte) ([]byte, bool) {
    17  	switch e.enc {
    18  	case Protobuf:
    19  		return e.doEncodeProtobuf(buf)
    20  	case LineProtocol:
    21  		return e.doEncodeLineProtocol(buf)
    22  	case JSON:
    23  		return e.doEncodeJSON(buf)
    24  	case PBJSON:
    25  		return e.doEncodePBJSON(buf)
    26  	default: // TODO: json
    27  		return nil, false
    28  	}
    29  }
    30  
    31  func (e *Encoder) doEncodeProtobuf(buf []byte) ([]byte, bool) {
    32  	var (
    33  		curSize,
    34  		pbptsSize int
    35  		trimmed = 1
    36  	)
    37  
    38  	for _, pt := range e.pts[e.lastPtsIdx:] {
    39  		if pt == nil {
    40  			continue
    41  		}
    42  
    43  		curSize += pt.Size()
    44  
    45  		// e.pbpts size larger than buf, we must trim some of points
    46  		// until size fit ok or MarshalTo will panic.
    47  		if curSize >= len(buf) {
    48  			if len(e.pbpts.Arr) <= 1 { // nothing to trim
    49  				e.lastErr = errTooSmallBuffer
    50  				return nil, false
    51  			}
    52  
    53  			for {
    54  				if pbptsSize = e.pbpts.Size(); pbptsSize > len(buf) {
    55  					e.pbpts.Arr = e.pbpts.Arr[:len(e.pbpts.Arr)-trimmed]
    56  					e.lastPtsIdx -= trimmed
    57  					trimmed *= 2
    58  				} else {
    59  					goto __doEncode
    60  				}
    61  			}
    62  		} else {
    63  			e.pbpts.Arr = append(e.pbpts.Arr, pt.pt)
    64  			e.lastPtsIdx++
    65  		}
    66  	}
    67  
    68  __doEncode:
    69  	e.trimmed = trimmed
    70  
    71  	if len(e.pbpts.Arr) == 0 {
    72  		return nil, false
    73  	}
    74  
    75  	defer func() {
    76  		e.pbpts.Arr = e.pbpts.Arr[:0]
    77  	}()
    78  
    79  	if n, err := e.pbpts.MarshalTo(buf); err != nil {
    80  		e.lastErr = err
    81  		return nil, false
    82  	} else {
    83  		if e.fn != nil {
    84  			if err := e.fn(len(e.pbpts.Arr), buf[:n]); err != nil {
    85  				e.lastErr = err
    86  				return nil, false
    87  			}
    88  		}
    89  
    90  		e.parts++
    91  		return buf[:n], true
    92  	}
    93  }
    94  
    95  func (e *Encoder) doEncodeLineProtocol(buf []byte) ([]byte, bool) {
    96  	curSize := 0
    97  	npts := 0
    98  
    99  	for _, pt := range e.pts[e.lastPtsIdx:] {
   100  		if pt == nil {
   101  			continue
   102  		}
   103  
   104  		lppt, err := pt.LPPoint()
   105  		if err != nil {
   106  			e.lastErr = err
   107  			continue
   108  		}
   109  
   110  		ptsize := lppt.StringSize()
   111  
   112  		if curSize+ptsize+1 > len(buf) { // extra +1 used to store the last '\n'
   113  			if curSize == 0 { // nothing added
   114  				e.lastErr = errTooSmallBuffer
   115  				return nil, false
   116  			}
   117  
   118  			if e.fn != nil {
   119  				if err := e.fn(npts, buf[:curSize]); err != nil {
   120  					e.lastErr = err
   121  					return nil, false
   122  				}
   123  			}
   124  			e.parts++
   125  			return buf[:curSize], true
   126  		} else {
   127  			e.lpPointBuf = lppt.AppendString(e.lpPointBuf)
   128  
   129  			copy(buf[curSize:], e.lpPointBuf[:ptsize])
   130  
   131  			// Always add '\n' to the end of current point, this may
   132  			// cause a _unneeded_ '\n' to the end of buf, it's ok for
   133  			// line-protocol parsing.
   134  			buf[curSize+ptsize] = '\n'
   135  			curSize += (ptsize + 1)
   136  
   137  			// clean buffer, next time AppendString() append from byte 0
   138  			e.lpPointBuf = e.lpPointBuf[:0]
   139  			e.lastPtsIdx++
   140  			npts++
   141  		}
   142  	}
   143  
   144  	if curSize > 0 {
   145  		e.parts++
   146  		if e.fn != nil { // NOTE: encode callback error will terminate encode
   147  			if err := e.fn(npts, buf[:curSize]); err != nil {
   148  				e.lastErr = err
   149  				return nil, false
   150  			}
   151  		}
   152  		return buf[:curSize], true
   153  	} else {
   154  		return nil, false
   155  	}
   156  }
   157  
   158  func (e *Encoder) doEncodeJSON(buf []byte) ([]byte, bool) {
   159  	return nil, false
   160  }
   161  
   162  func (e *Encoder) doEncodePBJSON(buf []byte) ([]byte, bool) {
   163  	return nil, false
   164  }