Files
zeekay f5aaeb712e Hanzo Graph — the engine, on zapdb, ZAP-native
Derived from Dgraph (github.com/dgraph-io/dgraph) at commit 64804bd2, Apache-2.0.
See NOTICE.

WHAT THIS IS. The graph engine as a Go library: posting lists, the DQL parser,
the type and tokenizer system, the index and schema layers, and the wire types.
39,170 lines of the upstream's 166,337.

THE STORE is github.com/luxfi/zapdb, a Badger fork that kept the package name,
the subpackages (options, pb, y) and the API — Open, OpenManaged, DB, Options —
so the 74 import sites are aliased rather than rewritten.

THE CODEC is ZAP. zapdb serializes with ZAP, not protobuf: its pb package builds
the ZAP types by default and the protobuf ones only under `-tags grpc`, a path
that does not compile (table/builder.go calls pb.Marshal, which that tag
removes). One call site in posting needed converting; every other type here is
Hanzo's own protobuf and is untouched.

NO TRANSPORT. An embedded engine dials nothing, so nothing here imports
google.golang.org/grpc. Removed: 20 transport functions in x, the generated
service stubs for Raft, Zero and Worker (1,657 lines), and the JWT helper —
identity belongs to IAM. The core called none of them.

NOT KEPT: worker, conn, raftwal, the cluster commands, the GraphQL layer and the
test harnesses. `query`, the DQL execution engine, went with them because it
depends on worker; parsing DQL is available here, executing it is not.

The history of the upstream project lives at github.com/dgraph-io/dgraph. This
repository begins at the derivation because three quarters of that history
describes code this fork does not carry.
2026-08-20 21:26:27 -07:00

142 lines
3.5 KiB
Go

/*
* SPDX-FileCopyrightText: © 2017-2026 Istari Digital, Inc.
* SPDX-License-Identifier: Apache-2.0
*/
package types
import (
"encoding/binary"
"math"
"strconv"
"strings"
"unsafe"
)
// BytesAsFloatArray(encoded) converts encoded into a []float32.
// If len(encoded) % 4 is not 0, it will ignore any trailing
// bytes, and simply convert 4 bytes at a time to generate the
// float64 entries.
// Current implementation assuming littleEndian encoding
func BytesAsFloatArray(encoded []byte) []float32 {
resultLen := len(encoded) / 4
if resultLen == 0 {
return []float32{}
}
retVal := make([]float32, resultLen)
for i := range resultLen {
retVal[i] = *(*float32)(unsafe.Pointer(&encoded[0]))
encoded = encoded[4:]
}
return retVal
}
// FloatArrayAsBytes(v) will create a byte array encoding
// v using LittleEndian format. This is sort of the inverse
// of BytesAsFloatArray, but note that we can always be successful
// converting to bytes, but the inverse is not feasible.
func FloatArrayAsBytes(v []float32) []byte {
retVal := make([]byte, 4*len(v))
offset := retVal
for i := range v {
bits := math.Float32bits(v[i])
binary.LittleEndian.PutUint32(offset, bits)
offset = offset[4:]
}
return retVal
}
func FloatArrayAsString(v []float32) string {
var sb strings.Builder
sb.WriteRune('[')
for i := range v {
sb.WriteString(strconv.FormatFloat(float64(v[i]), 'f', -1, 32))
if i != len(v)-1 {
sb.WriteRune(',')
}
}
sb.WriteRune(']')
return sb.String()
}
// TypeForValue tries to determine the most likely type based on a value. We only want to use this
// function when there's no schema type and no suggested storage type.
// Returns the guessed type or DefaultID if it couldn't be determined.
// If retval is non-nil, the parsed value is returned, useful in conjunction with ObjectValue().
func TypeForValue(v []byte) (TypeID, interface{}) {
s := string(v)
switch {
case v == nil || s == "":
break
// Possible boolean. Specific to "true" or "false".
case s[0] == 't', s[0] == 'T', s[0] == 'f', s[0] == 'F':
var b bool
// XXX: we dont use ParseBool here because it considers 't' and 'f' as values.
switch s {
case "true", "TRUE", "True":
b = true
return BoolID, b
case "false", "FALSE", "False":
return BoolID, b
}
// Possible datetime. Unfortunately, year-only value will fallthrough as int.
case checkDateTime(s):
if t, err := ParseTime(s); err == nil {
return DateTimeID, t
}
// Possible int.
case checkInt(s):
if i, err := strconv.ParseInt(s, 10, 64); err == nil {
return IntID, i
}
// Possible float.
case checkFloat(s):
if f, err := strconv.ParseFloat(s, 64); err == nil {
return FloatID, f
}
}
// TODO: Consider looking for vector type (vfloat). Not clear
// about this, because the natural encoding as
// "[ num, num, ... num ]" my look like a standard list type.
return DefaultID, nil
}
func isSign(d byte) bool {
return d == '-' || d == '+'
}
func isDigit(d byte) bool {
return d >= '0' && d <= '9'
}
func checkInt(s string) bool {
if isSign(s[0]) && len(s) > 1 {
s = s[1:]
}
return isDigit(s[0]) && !strings.ContainsAny(s[1:], ".Ee")
}
func checkFloat(s string) bool {
if isSign(s[0]) && len(s) > 1 {
s = s[1:]
}
if s[0] == '.' && len(s) > 1 {
// .012 is totally legit
return isDigit(s[1])
}
return isDigit(s[0]) && strings.ContainsAny(s[1:], ".Ee")
}
func checkDateTime(s string) bool {
if len(s) < 5 {
return false
}
return isDigit(s[0]) && isDigit(s[1]) && isDigit(s[2]) && isDigit(s[3]) && s[4] == '-'
}