in frequencies/items_sketch.go [107:181]
func NewFrequencyItemsSketchFromSlice[C comparable](slc []byte, hasher common.ItemSketchHasher[C], serde common.ItemSketchSerde[C]) (*ItemsSketch[C], error) {
if serde == nil {
return nil, errors.New("no SerDe provided")
}
pre0, err := checkPreambleSize(slc) //make sure preamble will fit
maxPreLongs := internal.FamilyEnum.Frequency.MaxPreLongs
preLongs := extractPreLongs(pre0) //Byte 0
serVer := extractSerVer(pre0) //Byte 1
familyID := extractFamilyID(pre0) //Byte 2
lgMaxMapSize := extractLgMaxMapSize(pre0) //Byte 3
lgCurMapSize := extractLgCurMapSize(pre0) //Byte 4
empty := (extractFlags(pre0) & _EMPTY_FLAG_MASK) != 0 //Byte 5
// Checks
preLongsEq1 := (preLongs == 1) //Byte 0
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 { //Byte 1
return nil, fmt.Errorf("possible corruption: ser ver must be %d: %d", _SER_VER, serVer)
}
actFamID := internal.FamilyEnum.Frequency.Id //Byte 2
if familyID != actFamID {
return nil, fmt.Errorf("possible corruption: familyID must be %d: %d", actFamID, familyID)
}
if empty && !preLongsEq1 { //Byte 5 and Byte 0
return nil, fmt.Errorf("(preLongs == 1) ^ empty == true")
}
if empty {
return NewFrequencyItemsSketchWithMaxMapSize[C](1<<_LG_MIN_MAP_SIZE, hasher, serde)
}
// Get full preamble
preArr := make([]int64, preLongs)
for j := 0; j < preLongs; j++ {
preArr[j] = int64(binary.LittleEndian.Uint64(slc[j<<3:]))
}
fis, err := NewFrequencyItemsSketch[C](lgMaxMapSize, lgCurMapSize, hasher, serde)
if err != nil {
return nil, err
}
fis.streamWeight = 0 // update after
fis.offset = preArr[3]
preBytes := preLongs << 3
activeItems := extractActiveItems(preArr[1])
// Get countArray
countArray := make([]int64, activeItems)
reqBytes := preBytes + activeItems*8 // count Arr only
if len(slc) < reqBytes {
return nil, fmt.Errorf("possible Corruption: Insufficient bytes in array: %d, %d", len(slc), reqBytes)
}
for j := 0; j < activeItems; j++ {
countArray[j] = int64(binary.LittleEndian.Uint64(slc[preBytes+j<<3:]))
}
// Get itemArray
itemsOffset := preBytes + (8 * activeItems)
itemArray, err := serde.DeserializeManyFromSlice(slc[itemsOffset:], 0, activeItems)
if err != nil {
return nil, err
}
// update the sketch
for j := 0; j < activeItems; j++ {
err := fis.UpdateMany(itemArray[j], countArray[j])
if err != nil {
return nil, err
}
}
fis.streamWeight = preArr[2] // override streamWeight due to updating
return fis, nil
}