func scanMeasurement(buf []byte, i int) (int, int, error) {
	if buf[i] == ',' {
		return -1, i, fmt.Errorf("missing measurement")
	}
	for {
		i++
		if i >= len(buf) {
			return -1, i, fmt.Errorf("missing fields")
		}
		if buf[i-1] == '\\' {
			continue
		}
		if buf[i] == ',' {
			return tagKeyState, i + 1, nil
		}
		if buf[i] == ' ' {
			return fieldsState, i, nil
		}
	}
}
scanMeasurement examines the measurement part of a Point, returning
the next state to move to, and the current location in the buffer.
package models  
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"hash/fnv"
	"math"
	"sort"
	"strconv"
	"strings"
	"time"
	"github.com/influxdata/influxdb/pkg/escape"
)
var (
	measurementEscapeCodes = map[byte][]byte{
		',': []byte(`\,`),
		' ': []byte(`\ `),
	}
	tagEscapeCodes = map[byte][]byte{
		',': []byte(`\,`),
		' ': []byte(`\ `),
		'=': []byte(`\=`),
	}
	ErrPointMustHaveAField = errors.New("point without fields is unsupported")
)
type Point interface {
	Name() string
	SetName(string)
	Tags() Tags
	AddTag(key, value string)
	SetTags(tags Tags)
	Fields() Fields
	Time() time.Time
	SetTime(t time.Time)
	UnixNano() int64
	HashID() uint64
	Key() []byte
	Data() []byte
	SetData(buf []byte)
	String() string
	MarshalBinary() ([]byte, error)
	PrecisionString(precision string) string
	RoundedString(d time.Duration) string
}
type Points []Point
func (a Points) Len() int           { return len(a) }
func (a Points) Less(i, j int) bool { return a[i].Time().Before(a[j].Time()) }
func (a Points) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
type point struct {
	time time.Time
	key []byte
	fields []byte
	ts []byte
	data []byte
	cachedFields map[string]interface{}
	cachedName string
}
const (
	maxInt64Digits = 19
	minInt64Digits = 20
	maxFloat64Digits = 25
	minFloat64Digits = 27
)
func ParsePoints(buf []byte) ([]Point, error) {
	return ParsePointsWithPrecision(buf, time.Now().UTC(), "n")
}
func ParsePointsString(buf string) ([]Point, error) {
	return ParsePoints([]byte(buf))
}
func ParseKey(buf string) (string, Tags, error) {
	_, keyBuf, err := scanKey([]byte(buf), 0)
	tags := parseTags([]byte(buf))
	return string(keyBuf), tags, err
}
func ParsePointsWithPrecision(buf []byte, defaultTime time.Time, precision string) ([]Point, error) {
	points := []Point{}
	var (
		pos    int
		block  []byte
		failed []string
	)
	for {
		pos, block = scanLine(buf, pos)
		pos++
		if len(block) == 0 {
			break
		}
		start := skipWhitespace(block, 0)
		if start >= len(block) {
			continue
		}
		if block[start] == '#' {
			continue
		}
		if block[len(block)-1] == '\n' {
			block = block[:len(block)-1]
		}
		pt, err := parsePoint(block[start:len(block)], defaultTime, precision)
		if err != nil {
			failed = append(failed, fmt.Sprintf("unable to parse '%s': %v", string(block[start:len(block)]), err))
		} else {
			points = append(points, pt)
		}
		if pos >= len(buf) {
			break
		}
	}
	if len(failed) > 0 {
		return points, fmt.Errorf("%s", strings.Join(failed, "\n"))
	}
	return points, nil
}
func parsePoint(buf []byte, defaultTime time.Time, precision string) (Point, error) {
	pos, key, err := scanKey(buf, 0)
	if err != nil {
		return nil, err
	}
	if len(key) == 0 {
		return nil, fmt.Errorf("missing measurement")
	}
	pos, fields, err := scanFields(buf, pos)
	if err != nil {
		return nil, err
	}
	if len(fields) == 0 {
		return nil, fmt.Errorf("missing fields")
	}
	pos, ts, err := scanTime(buf, pos)
	if err != nil {
		return nil, err
	}
	pt := &point{
		key:    key,
		fields: fields,
		ts:     ts,
	}
	if len(ts) == 0 {
		pt.time = defaultTime
		pt.SetPrecision(precision)
	} else {
		ts, err := strconv.ParseInt(string(ts), 10, 64)
		if err != nil {
			return nil, err
		}
		pt.time, err = SafeCalcTime(ts, precision)
		if err != nil {
			return nil, err
		}
	}
	return pt, nil
}
func GetPrecisionMultiplier(precision string) int64 {
	d := time.Nanosecond
	switch precision {
	case "u":
		d = time.Microsecond
	case "ms":
		d = time.Millisecond
	case "s":
		d = time.Second
	case "m":
		d = time.Minute
	case "h":
		d = time.Hour
	}
	return int64(d)
}
func scanKey(buf []byte, i int) (int, []byte, error) {
	start := skipWhitespace(buf, i)
	i = start
	sorted := true
	indices := make([]int, 100)
	commas := 0
	state, i, err := scanMeasurement(buf, i)
	if err != nil {
		return i, buf[start:i], err
	}
	if state == tagKeyState {
		i, commas, indices, err = scanTags(buf, i, indices)
		if err != nil {
			return i, buf[start:i], err
		}
	}
	for j := 0; j < commas/2; j++ {
		_, left := scanTo(buf[indices[j]:indices[j+1]-1], 0, '=')
		_, right := scanTo(buf[indices[commas-j-1]:indices[commas-j]-1], 0, '=')
		if bytes.Equal(left, right) {
			return i, buf[start:i], fmt.Errorf("duplicate tags")
		}
		if bytes.Compare(left, right) > 0 {
			sorted = false
		}
	}
	if !sorted && commas > 0 {
		measurement := buf[start : indices[0]-1]
		indices := indices[:commas]
		insertionSort(0, commas, buf, indices)
		b := make([]byte, len(buf[start:i]))
		pos := copy(b, measurement)
		for _, i := range indices {
			b[pos] = ','
			pos++
			_, v := scanToSpaceOr(buf, i, ',')
			pos += copy(b[pos:], v)
		}
		return i, b, nil
	}
	return i, buf[start:i], nil
}
const (
	tagKeyState = iota
	tagValueState
	fieldsState
)