in frequencies/longs_sketch.go [101:174]
func NewLongsSketchFromSlice(slc []byte) (*LongsSketch, error) {
pre0, err := checkPreambleSize(slc)
if err != nil {
return nil, err
}
maxPreLongs := internal.FamilyEnum.Frequency.MaxPreLongs
preLongs := extractPreLongs(pre0)
serVer := extractSerVer(pre0)
familyID := extractFamilyID(pre0)
lgMaxMapSize := extractLgMaxMapSize(pre0)
lgCurMapSize := extractLgCurMapSize(pre0)
empty := (extractFlags(pre0) & _EMPTY_FLAG_MASK) != 0
// Checks
preLongsEq1 := preLongs == 1
preLongsEqMax := preLongs == maxPreLongs
if !preLongsEq1 && !preLongsEqMax {
return nil, fmt.Errorf("possible Corruption: PreLongs must be 1 or %d: %d", maxPreLongs, preLongs)
}
if serVer != _SER_VER {
return nil, fmt.Errorf("possible Corruption: Ser Ver must be %d: %d", _SER_VER, serVer)
}
actFamID := internal.FamilyEnum.Frequency.Id
if familyID != actFamID {
return nil, fmt.Errorf("possible Corruption: FamilyID must be %d: %d", actFamID, familyID)
}
if empty && !preLongsEq1 {
return nil, fmt.Errorf("possible Corruption: Empty Flag set incorrectly: %t", preLongsEq1)
}
if empty {
return NewLongsSketch(lgMaxMapSize, _LG_MIN_MAP_SIZE)
}
// get full preamble
preArr := make([]int64, preLongs)
for i := 0; i < preLongs; i++ {
preArr[i] = int64(binary.LittleEndian.Uint64(slc[i<<3:]))
}
fls, err := NewLongsSketch(lgMaxMapSize, lgCurMapSize)
if err != nil {
return nil, err
}
fls.streamWeight = 0 //update after
fls.offset = preArr[3]
preBytes := preLongs << 3
activeItems := extractActiveItems(preArr[1])
// Get countArray
countArray := make([]int64, activeItems)
reqBytes := preBytes + 2*activeItems*8 //count Arr + Items Arr
if len(slc) < reqBytes {
return nil, fmt.Errorf("possible Corruption: Insufficient bytes in array: %d, %d", len(slc), reqBytes)
}
for i := 0; i < activeItems; i++ {
countArray[i] = int64(binary.LittleEndian.Uint64(slc[preBytes+(i<<3):]))
}
// Get itemArray
itemsOffset := preBytes + (8 * activeItems)
itemArray := make([]int64, activeItems)
for i := 0; i < activeItems; i++ {
itemArray[i] = int64(binary.LittleEndian.Uint64(slc[itemsOffset+(i<<3):]))
}
// UpdateMany the sketch
for i := 0; i < activeItems && err == nil; i++ {
err = fls.UpdateMany(itemArray[i], countArray[i])
}
if err != nil {
return nil, err
}
fls.streamWeight = preArr[2] //override streamWeight due to updating
return fls, nil
}