package fbs import ( "encoding/base64" "encoding/json" "fmt" "strings" "sync" "git.loyso.art/frx/eway/internal/entity" flatbuffers "github.com/google/flatbuffers/go" ) var builderPool = sync.Pool{ New: func() any { builder := flatbuffers.NewBuilder(1024) return builder }, } func getBuilder() *flatbuffers.Builder { builder := builderPool.Get().(*flatbuffers.Builder) return builder } func putBuilder(builder *flatbuffers.Builder) { // builder.Reset() // builderPool.Put(builder) } func MakeDomainGoodItems(in ...entity.GoodsItem) []byte { builder := getBuilder() defer putBuilder(builder) offsets := make([]flatbuffers.UOffsetT, 0, len(in)) for _, item := range in { inFB := makeDomainGoodItem(builder, item) offsets = append(offsets, inFB) } GoodItemsStartItemsVector(builder, len(offsets)) for i := len(offsets) - 1; i >= 0; i-- { builder.PrependUOffsetT(offsets[i]) } goodItemsVec := builder.EndVector(len(offsets)) GoodItemsStart(builder) GoodItemsAddItems(builder, goodItemsVec) out := GoodItemsEnd(builder) builder.Finish(out) return builder.FinishedBytes() } func MakeDomainGoodItemFinished(in entity.GoodsItem) []byte { builder := getBuilder() defer putBuilder(builder) item := makeDomainGoodItem(builder, in) builder.Finish(item) return builder.FinishedBytes() } func makeDomainGoodItem(builder *flatbuffers.Builder, in entity.GoodsItem) flatbuffers.UOffsetT { sku := builder.CreateString(in.Articul) photo := builder.CreateString(strings.Join(in.PhotoURLs, ";")) name := builder.CreateString(in.Name) descBase64 := base64.RawStdEncoding.EncodeToString([]byte(in.Description)) desc := builder.CreateString(descBase64) var cat flatbuffers.UOffsetT if in.Category != "" { cat = builder.CreateString(in.Category) } t := builder.CreateString(in.Type) parametersData, _ := json.Marshal(in.Parameters) parameters := builder.CreateByteString(parametersData) producer := builder.CreateString(in.Producer) GoodItemStart(builder) GoodItemAddSku(builder, sku) GoodItemAddPhoto(builder, photo) GoodItemAddName(builder, name) GoodItemAddDescription(builder, desc) if in.Category != "" { GoodItemAddCategory(builder, cat) } GoodItemAddType(builder, t) GoodItemAddProducer(builder, producer) GoodItemAddPack(builder, int16(in.Pack)) GoodItemAddStep(builder, int16(in.Step)) GoodItemAddPrice(builder, float32(in.Price)) GoodItemAddTariff(builder, float32(in.TariffPrice)) GoodItemAddCart(builder, int64(in.Cart)) GoodItemAddStock(builder, int16(in.Stock)) GoodItemAddParameters(builder, parameters) return GoodItemEnd(builder) } func ParseGoodsItem(data []byte) (item entity.GoodsItem, err error) { itemFBS := GetRootAsGoodItem(data, 0) item.Articul = string(itemFBS.Sku()) item.PhotoURLs = strings.Split(string(itemFBS.Photo()), ";") item.Name = string(itemFBS.Name()) description, err := base64.RawStdEncoding.DecodeString(string(itemFBS.Description())) if err != nil { return item, fmt.Errorf("decoding description from base64: %w", err) } item.Description = string(description) if value := itemFBS.Category(); value != nil { item.Category = string(value) } item.Type = string(itemFBS.Type()) item.Producer = string(itemFBS.Producer()) item.Pack = int(itemFBS.Pack()) item.Step = int(itemFBS.Step()) item.Price = float64(itemFBS.Price()) item.TariffPrice = float64(itemFBS.Tariff()) item.Cart = itemFBS.Cart() item.Stock = int(itemFBS.Stock()) item.Parameters = map[string]string{} err = json.Unmarshal(itemFBS.Parameters(), &item.Parameters) if err != nil { return item, fmt.Errorf("unmarshalling data: %w", err) } return item, nil } func ParseCategory(data []byte) (category entity.Category) { categoryFBS := GetRootAsCategory(data, 0) category.ID = categoryFBS.Id() category.Name = string(categoryFBS.Name()) return category } func MakeCategoryFinished(category entity.Category) []byte { builder := getBuilder() defer putBuilder(builder) offset := makeCategory(builder, category) builder.Finish(offset) return builder.FinishedBytes() } func makeCategory(builder *flatbuffers.Builder, category entity.Category) flatbuffers.UOffsetT { name := builder.CreateString(category.Name) CategoryStart(builder) CategoryAddId(builder, category.ID) CategoryAddName(builder, name) return CategoryEnd(builder) }