commit 5b39bcd43a1ff0dd6405d023e15d2fa7153a0957
parent bd996eec0a07992ae60d86323e47ba3b485ba11b
Author: Vetle Haflan <vetle.haflan@luxsave.com>
Date: Mon, 8 Jun 2020 23:07:11 +0200
Use binary instead of strconv for byte <-> uint64
Should fix #12
Diffstat:
4 files changed, 18 insertions(+), 44 deletions(-)
diff --git a/internal/database/database.go b/internal/database/database.go
@@ -1,10 +1,10 @@
package database
import (
+ "encoding/binary"
"errors"
"fmt"
"log"
- "strconv"
"time"
"go.etcd.io/bbolt"
@@ -68,15 +68,15 @@ func GetDB() *bbolt.DB {
// often repeated for IDs. It is assumed that the data will parse successfully
// (i.e. type checking is performed in an earlier stage).
// If the parsing fails, the function therefore panics
-func BytesToUint64(byteData []byte) uint64 {
- uint64Data, err := strconv.ParseUint(string(byteData), 10, 64)
- check(err)
- return uint64Data
+func BytesToUint64(b []byte) uint64 {
+ return binary.BigEndian.Uint64(b)
}
// Uint64ToBytes converts a uint64 formatted number to a byte array
-func Uint64ToBytes(uint64Data uint64) []byte {
- return []byte(strconv.FormatUint(uint64Data, 10))
+func Uint64ToBytes(ui64 uint64) (b []byte) {
+ b = make([]byte, 8)
+ binary.BigEndian.PutUint64(b, ui64)
+ return
}
// PrintBucket simply prints the K-V pairs in the bucket
diff --git a/internal/events/events.go b/internal/events/events.go
@@ -5,7 +5,6 @@ import (
"fmt"
"log"
"sermoni/internal/database"
- "strconv"
"go.etcd.io/bbolt"
)
@@ -84,7 +83,7 @@ func Add(event *Event) error {
if err != nil {
return err
}
- id := []byte(strconv.FormatUint(idInt, 10))
+ id := database.Uint64ToBytes(idInt)
event.ID = idInt
// Create the event bucket and fill it with data from event
diff --git a/internal/services/services.go b/internal/services/services.go
@@ -1,12 +1,12 @@
package services
import (
+ "encoding/binary"
"errors"
"fmt"
"log"
"sermoni/internal/database"
"sermoni/internal/events"
- "strconv"
"go.etcd.io/bbolt"
)
@@ -43,7 +43,9 @@ func GetByToken(token string) *Service {
// GetByID returns the service structure associated with the given uint64-formatted
// service ID, if that service exists. Otherwise returns nil
func GetByID(id uint64) *Service {
- return get([]byte(strconv.FormatUint(id, 10)))
+ idb := make([]byte, 8)
+ binary.BigEndian.PutUint64(idb, id)
+ return get(idb)
}
// GetAll returns all services in the database (TODO)
@@ -78,7 +80,7 @@ func GetAll() []*Service {
// Delete deletes the given service if it exists, and all events for said service, if any
func Delete(intID uint64) error {
db := database.GetDB()
- serviceID := []byte(strconv.FormatUint(intID, 10))
+ serviceID := database.Uint64ToBytes(intID)
return db.Update(func(tx *bbolt.Tx) (err error) {
sb := tx.Bucket(database.BucketKeyServices)
stb := tx.Bucket(database.BucketKeyServiceTokens)
@@ -167,7 +169,7 @@ func Add(service *Service) error {
if serviceIDint, err = b.NextSequence(); err != nil {
return err
}
- serviceID = []byte(strconv.FormatUint(serviceIDint, 10))
+ serviceID = database.Uint64ToBytes(serviceIDint)
if sb, err = b.CreateBucket(serviceID); err != nil {
return err
}
@@ -177,11 +179,11 @@ func Add(service *Service) error {
if err = sb.Put(keyServiceDescription, []byte(service.Description)); err != nil {
return err
}
- periodStr := strconv.FormatUint(service.ExpectationPeriod, 10)
+ periodStr := database.Uint64ToBytes(service.ExpectationPeriod)
if err = sb.Put(keyServicePeriod, []byte(periodStr)); err != nil {
return err
}
- maxEventsStr := strconv.FormatUint(service.MaxNumberEvents, 10)
+ maxEventsStr := database.Uint64ToBytes(service.MaxNumberEvents)
if err = sb.Put(keyServiceMaxEvents, []byte(maxEventsStr)); err != nil {
return err
}
@@ -198,7 +200,6 @@ func Add(service *Service) error {
// fromBucket populates the service struct with data from the given service bucket
// TODO: Consider failing on missing fields and generally choosing an approach more similar to Event.fromBucket
func (service *Service) fromBucket(id []byte, sb *bbolt.Bucket) {
- // Ignoring this error, because it shouldn't be possible
idInt := database.BytesToUint64(id)
service.ID = idInt
if name := sb.Get(keyServiceName); name != nil {
@@ -208,26 +209,10 @@ func (service *Service) fromBucket(id []byte, sb *bbolt.Bucket) {
service.Description = string(description)
}
if period := sb.Get(keyServicePeriod); period != nil {
- // Quick fix: Convert to string, then int
- // Uses default value 0 if an error occurs
- intPeriod, err := strconv.ParseUint(string(period), 10, 64)
- if err == nil {
- service.ExpectationPeriod = intPeriod
- } else {
- log.Println("Couldn't convert period to int for service")
- service.ExpectationPeriod = 0
- }
+ service.ExpectationPeriod = database.BytesToUint64(period)
}
if maxevents := sb.Get(keyServiceMaxEvents); maxevents != nil {
- // Quick fix: Convert to string, then int
- // Uses default value 0 if an error occurs
- intMaxEvents, err := strconv.ParseUint(string(maxevents), 10, 64)
- if err == nil {
- service.MaxNumberEvents = intMaxEvents
- } else {
- log.Println("Couldn't convert max num events to int for service")
- service.MaxNumberEvents = 0
- }
+ service.MaxNumberEvents = database.BytesToUint64(maxevents)
}
}
diff --git a/internal/services/services_test.go b/internal/services/services_test.go
@@ -5,19 +5,9 @@ import (
"os"
"sermoni/internal/config"
"sermoni/internal/database"
- "strconv"
"testing"
)
-// intID gets uint64 from bytes
-func intID(id []byte) uint64 {
- idInt, err := strconv.ParseUint(string(id), 10, 64)
- if err != nil {
- return 0
- }
- return idInt
-}
-
func (s1 *Service) equals(s2 *Service) bool {
switch {
case s1.ID != s2.ID: