Ejemplo n.º 1
0
// ReadIndexDefinition reads an IndexDefinition from the buffer.
func ReadIndexDefinition(buf Buffer) (i ds.IndexDefinition, err error) {
	defer recoverTo(&err)

	i.Kind, _, err = cmpbin.ReadString(buf)
	panicIf(err)

	anc, err := buf.ReadByte()
	panicIf(err)

	i.Ancestor = anc == 1

	for {
		ctrl := byte(0)
		ctrl, err = buf.ReadByte()
		panicIf(err)
		if ctrl == 0 {
			break
		}
		if len(i.SortBy) > MaxIndexColumns {
			err = fmt.Errorf("datastore: Got over %d sort orders", MaxIndexColumns)
			return
		}

		sb, err := ReadIndexColumn(buf)
		panicIf(err)

		i.SortBy = append(i.SortBy, sb)
	}

	return
}
Ejemplo n.º 2
0
// ReadPropertyMap reads a PropertyMap from the buffer. `context` and
// friends behave the same way that they do for ReadKey.
func ReadPropertyMap(buf Buffer, context KeyContext, appid, namespace string) (pm ds.PropertyMap, err error) {
	defer recoverTo(&err)

	numRows := uint64(0)
	numRows, _, e := cmpbin.ReadUint(buf)
	panicIf(e)
	if numRows > ReadPropertyMapReasonableLimit {
		err = fmt.Errorf("helper: tried to decode map with huge number of rows %d", numRows)
		return
	}

	pm = make(ds.PropertyMap, numRows)

	name, prop := "", ds.Property{}
	for i := uint64(0); i < numRows; i++ {
		name, _, e = cmpbin.ReadString(buf)
		panicIf(e)

		numProps, _, e := cmpbin.ReadUint(buf)
		panicIf(e)
		if numProps > ReadPropertyMapReasonableLimit {
			err = fmt.Errorf("helper: tried to decode map with huge number of properties %d", numProps)
			return
		}
		props := make([]ds.Property, 0, numProps)
		for j := uint64(0); j < numProps; j++ {
			prop, err = ReadProperty(buf, context, appid, namespace)
			panicIf(err)
			props = append(props, prop)
		}
		pm[name] = props
	}
	return
}
Ejemplo n.º 3
0
// ReadKey deserializes a key from the buffer. The value of context must match
// the value of context that was passed to WriteKey when the key was encoded.
// If context == WithoutContext, then the appid and namespace parameters are
// used in the decoded Key. Otherwise they're ignored.
func ReadKey(buf Buffer, context KeyContext, appid, namespace string) (ret *ds.Key, err error) {
	defer recoverTo(&err)
	actualCtx, e := buf.ReadByte()
	panicIf(e)

	actualAid, actualNS := "", ""
	if actualCtx == 1 {
		actualAid, _, e = cmpbin.ReadString(buf)
		panicIf(e)
		actualNS, _, e = cmpbin.ReadString(buf)
		panicIf(e)
	} else if actualCtx != 0 {
		err = fmt.Errorf("helper: expected actualCtx to be 0 or 1, got %d", actualCtx)
		return
	}

	if context == WithoutContext {
		// overrwrite with the supplied ones
		actualAid = appid
		actualNS = namespace
	}

	toks := []ds.KeyTok{}
	for {
		ctrlByte, e := buf.ReadByte()
		panicIf(e)
		if ctrlByte == 0 {
			break
		}
		if len(toks)+1 > ReadKeyNumToksReasonableLimit {
			err = fmt.Errorf(
				"helper: tried to decode huge key with > %d tokens",
				ReadKeyNumToksReasonableLimit)
			return
		}

		tok, e := ReadKeyTok(buf)
		panicIf(e)

		toks = append(toks, tok)
	}

	return ds.NewKeyToks(actualAid, actualNS, toks), nil
}
Ejemplo n.º 4
0
// ReadIndexColumn reads an IndexColumn from the buffer.
func ReadIndexColumn(buf Buffer) (c ds.IndexColumn, err error) {
	defer recoverTo(&err)

	dir, err := buf.ReadByte()
	panicIf(err)

	c.Descending = dir != 0
	c.Property, _, err = cmpbin.ReadString(buf)
	return
}
Ejemplo n.º 5
0
// ReadProperty reads a Property from the buffer. `context`, `appid`, and
// `namespace` behave the same way they do for ReadKey, but only have an
// effect if the decoded property has a Key value.
func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds.Property, err error) {
	val := interface{}(nil)
	b, err := buf.ReadByte()
	if err != nil {
		return
	}
	is := ds.ShouldIndex
	if (b & 0x80) == 0 {
		is = ds.NoIndex
	}
	switch ds.PropertyType(b & 0x7f) {
	case ds.PTNull:
	case ds.PTBool:
		b, err = buf.ReadByte()
		val = (b != 0)
	case ds.PTInt:
		val, _, err = cmpbin.ReadInt(buf)
	case ds.PTFloat:
		val, _, err = cmpbin.ReadFloat64(buf)
	case ds.PTString:
		val, _, err = cmpbin.ReadString(buf)
	case ds.PTBytes:
		val, _, err = cmpbin.ReadBytes(buf)
	case ds.PTTime:
		val, err = ReadTime(buf)
	case ds.PTGeoPoint:
		val, err = ReadGeoPoint(buf)
	case ds.PTKey:
		val, err = ReadKey(buf, context, appid, namespace)
	case ds.PTBlobKey:
		s := ""
		if s, _, err = cmpbin.ReadString(buf); err != nil {
			break
		}
		val = blobstore.Key(s)
	default:
		err = fmt.Errorf("read: unknown type! %v", b)
	}
	if err == nil {
		err = p.SetValue(val, is)
	}
	return
}
Ejemplo n.º 6
0
// ReadKeyTok reads a KeyTok from the buffer. You usually want ReadKey
// instead of this.
func ReadKeyTok(buf Buffer) (ret ds.KeyTok, err error) {
	defer recoverTo(&err)
	e := error(nil)
	ret.Kind, _, e = cmpbin.ReadString(buf)
	panicIf(e)

	typ, e := buf.ReadByte()
	panicIf(e)

	switch ds.PropertyType(typ) {
	case ds.PTString:
		ret.StringID, _, err = cmpbin.ReadString(buf)
	case ds.PTInt:
		ret.IntID, _, err = cmpbin.ReadInt(buf)
		if err == nil && ret.IntID <= 0 {
			err = errors.New("helper: decoded key with empty stringID and zero/negative intID")
		}
	default:
		err = fmt.Errorf("helper: invalid type %s", ds.PropertyType(typ))
	}
	return
}
Ejemplo n.º 7
0
// ReadIndexColumn reads an IndexColumn from the buffer.
func ReadIndexColumn(buf Buffer) (c ds.IndexColumn, err error) {
	defer recoverTo(&err)

	dir, err := buf.ReadByte()
	panicIf(err)

	switch dir {
	case 0:
		c.Direction = ds.ASCENDING
	default:
		c.Direction = ds.DESCENDING
	}
	c.Property, _, err = cmpbin.ReadString(buf)
	return
}