Files
eway/internal/encoding/fbs/helpers.go
2024-02-11 15:50:43 +03:00

194 lines
5.1 KiB
Go

package fbs
import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"
"sync"
"time"
"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)
var w, h, l float32
if in.Sizes != (entity.GoodsItemSize{}) {
w = float32(in.Sizes.Width.AdjustTo(entity.DimensionKindCentimeter).Value)
h = float32(in.Sizes.Height.AdjustTo(entity.DimensionKindCentimeter).Value)
l = float32(in.Sizes.Length.AdjustTo(entity.DimensionKindCentimeter).Value)
}
sizes := CreateDimensions(builder, w, h, l)
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))
GoodItemAddSizes(builder, sizes)
GoodItemAddParameters(builder, parameters)
GoodItemAddCreatedAt(builder, in.CreatedAt.Unix())
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{}
parameters := itemFBS.Parameters()
if len(parameters) > 0 {
err = json.Unmarshal(itemFBS.Parameters(), &item.Parameters)
if err != nil {
return item, fmt.Errorf("unmarshalling data: %w", err)
}
}
sizes := itemFBS.Sizes(nil)
w := float64(sizes.Width())
h := float64(sizes.Height())
l := float64(sizes.Length())
item.Sizes = entity.GoodsItemSize{
Width: entity.NewMilimeterDimension(w),
Height: entity.NewMilimeterDimension(h),
Length: entity.NewMilimeterDimension(l),
}
createdAt := itemFBS.CreatedAt()
if createdAt > 0 {
item.CreatedAt = time.Unix(createdAt, 0)
}
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)
}