diff --git a/db.go b/db.go index 1b8561b..8fa75e2 100644 --- a/db.go +++ b/db.go @@ -201,7 +201,7 @@ func Query[TResult any](db *DB, sql string, vars map[string]interface{}) (*[]Que return res.Result, nil } -func Create[TResult any, TWhat models.TableOrRecord](db *DB, what TWhat, data interface{}) (*TResult, error) { +func Create[TResult any, TWhat TableOrRecord](db *DB, what TWhat, data interface{}) (*TResult, error) { var res connection.RPCResponse[TResult] if err := db.con.Send(&res, "create", what, data); err != nil { return nil, err @@ -210,7 +210,7 @@ func Create[TResult any, TWhat models.TableOrRecord](db *DB, what TWhat, data in return res.Result, nil } -func Select[TResult any, TWhat models.TableOrRecord](db *DB, what TWhat) (*TResult, error) { +func Select[TResult any, TWhat TableOrRecord](db *DB, what TWhat) (*TResult, error) { var res connection.RPCResponse[TResult] if err := db.con.Send(&res, "select", what); err != nil { @@ -226,16 +226,16 @@ func Patch(db *DB, what interface{}, patches []PatchData) (*[]PatchData, error) return patchRes.Result, err } -func Delete[TWhat models.TableOrRecord](db *DB, what TWhat) error { +func Delete[TWhat TableOrRecord](db *DB, what TWhat) error { return db.con.Send(nil, "delete", what) } -func Upsert[TWhat models.TableOrRecord](db *DB, what TWhat, data interface{}) error { +func Upsert[TWhat TableOrRecord](db *DB, what TWhat, data interface{}) error { return db.con.Send(nil, "upsert", what, data) } // Update a table or record in the database like a PUT request. -func Update[TResult any, TWhat models.TableOrRecord](db *DB, what TWhat, data interface{}) (*TResult, error) { +func Update[TResult any, TWhat TableOrRecord](db *DB, what TWhat, data interface{}) (*TResult, error) { var res connection.RPCResponse[TResult] if err := db.con.Send(&res, "update", what, data); err != nil { return nil, err diff --git a/pkg/models/cbor.go b/pkg/models/cbor.go index 5531a68..1863feb 100644 --- a/pkg/models/cbor.go +++ b/pkg/models/cbor.go @@ -3,60 +3,68 @@ package models import ( "io" "reflect" - "time" "github.com/fxamacker/cbor/v2" "github.com/surrealdb/surrealdb.go/internal/codec" ) -type CustomCBORTag uint64 - var ( - NoneTag CustomCBORTag = 6 - TableNameTag CustomCBORTag = 7 - RecordIDTag CustomCBORTag = 8 - UUIDStringTag CustomCBORTag = 9 - DecimalStringTag CustomCBORTag = 10 - DateTimeCompactString CustomCBORTag = 12 - DurationStringTag CustomCBORTag = 13 - DurationCompactTag CustomCBORTag = 14 - BinaryUUIDTag CustomCBORTag = 37 - GeometryPointTag CustomCBORTag = 88 - GeometryLineTag CustomCBORTag = 89 - GeometryPolygonTag CustomCBORTag = 90 - GeometryMultiPointTag CustomCBORTag = 91 - GeometryMultiLineTag CustomCBORTag = 92 - GeometryMultiPolygonTag CustomCBORTag = 93 - GeometryCollectionTag CustomCBORTag = 94 + TagNone uint64 = 6 + TagTable uint64 = 7 + TagRecordID uint64 = 8 + TagCustomDatetime uint64 = 12 + TagCustomDuration uint64 = 14 + TagFuture uint64 = 15 + + TagStringUUID uint64 = 9 + TagStringDecimal uint64 = 10 + TagStringDuration uint64 = 13 + + TagSpecBinaryUUID uint64 = 37 + + TagRange uint64 = 49 + TagBoundIncluded uint64 = 50 + TagBoundExcluded uint64 = 51 + + TagGeometryPoint uint64 = 88 + TagGeometryLine uint64 = 89 + TagGeometryPolygon uint64 = 90 + TagGeometryMultiPoint uint64 = 91 + TagGeometryMultiLine uint64 = 92 + TagGeometryMultiPolygon uint64 = 93 + TagGeometryCollection uint64 = 94 ) func registerCborTags() cbor.TagSet { - customTags := map[CustomCBORTag]interface{}{ - GeometryPointTag: GeometryPoint{}, - GeometryLineTag: GeometryLine{}, - GeometryPolygonTag: GeometryPolygon{}, - GeometryMultiPointTag: GeometryMultiPoint{}, - GeometryMultiLineTag: GeometryMultiLine{}, - GeometryMultiPolygonTag: GeometryMultiPolygon{}, - GeometryCollectionTag: GeometryCollection{}, - - TableNameTag: Table(""), - //UUIDStringTag: UUID(""), - DecimalStringTag: Decimal(""), - BinaryUUIDTag: UUID{}, - NoneTag: CustomNil{}, - - DateTimeCompactString: CustomDateTime(time.Now()), - DurationStringTag: CustomDurationStr("2w"), - //DurationCompactTag: CustomDuration(0), + customTags := map[uint64]interface{}{ + TagNone: CustomNil{}, + TagTable: Table(""), + TagRecordID: RecordID{}, + + TagCustomDatetime: CustomDateTime{}, + TagCustomDuration: CustomDuration{}, + TagFuture: Future{}, + + TagStringUUID: UUIDString(""), + TagStringDecimal: DecimalString(""), + TagStringDuration: CustomDurationString(""), + + TagSpecBinaryUUID: UUID{}, + + TagGeometryPoint: GeometryPoint{}, + TagGeometryLine: GeometryLine{}, + TagGeometryPolygon: GeometryPolygon{}, + TagGeometryMultiPoint: GeometryMultiPoint{}, + TagGeometryMultiLine: GeometryMultiLine{}, + TagGeometryMultiPolygon: GeometryMultiPolygon{}, + TagGeometryCollection: GeometryCollection{}, } - tags := cbor.NewTagSet() for tag, customType := range customTags { err := tags.Add( cbor.TagOptions{EncTag: cbor.EncTagRequired, DecTag: cbor.DecTagRequired}, reflect.TypeOf(customType), - uint64(tag), + tag, ) if err != nil { panic(err) diff --git a/pkg/models/cbor_test.go b/pkg/models/cbor_test.go index 85150bc..dd8bf27 100644 --- a/pkg/models/cbor_test.go +++ b/pkg/models/cbor_test.go @@ -68,14 +68,14 @@ func TestForRequestPayload(t *testing.T) { params := []interface{}{ "SELECT marketing, count() FROM $tb GROUP BY marketing", map[string]interface{}{ - "tb": Table("person"), - "line": GeometryLine{NewGeometryPoint(11.11, 22.22), NewGeometryPoint(33.33, 44.44)}, - "datetime": time.Now(), - "testNone": None, - "testNil": nil, - "duration": time.Duration(340), - // "custom_duration": CustomDuration(340), - "custom_datetime": CustomDateTime(time.Now()), + "tb": Table("person"), + "line": GeometryLine{NewGeometryPoint(11.11, 22.22), NewGeometryPoint(33.33, 44.44)}, + "datetime": time.Now(), + "testNone": None, + "testNil": nil, + "duration": time.Duration(340), + "custom_duration": CustomDuration{340}, + "custom_datetime": CustomDateTime{time.Now()}, }, } @@ -94,3 +94,118 @@ func TestForRequestPayload(t *testing.T) { fmt.Println(diagStr) } + +func TestRange_GetJoinString(t *testing.T) { + t.Run("begin excluded, end excluded", func(s *testing.T) { + r := &Range[int, BoundExcluded[int], BoundExcluded[int]]{ + Begin: &BoundExcluded[int]{0}, + End: &BoundExcluded[int]{10}, + } + assert.Equal(t, ">..", r.GetJoinString()) + }) + + t.Run("begin excluded, end included", func(t *testing.T) { + r := Range[int, BoundExcluded[int], BoundIncluded[int]]{ + Begin: &BoundExcluded[int]{0}, + End: &BoundIncluded[int]{10}, + } + assert.Equal(t, ">..=", r.GetJoinString()) + }) + + t.Run("begin included, end excluded", func(t *testing.T) { + r := Range[int, BoundIncluded[int], BoundExcluded[int]]{ + Begin: &BoundIncluded[int]{0}, + End: &BoundExcluded[int]{10}, + } + assert.Equal(t, "..", r.GetJoinString()) + }) + + t.Run("begin included, end included", func(t *testing.T) { + r := Range[int, BoundIncluded[int], BoundIncluded[int]]{ + Begin: &BoundIncluded[int]{0}, + End: &BoundIncluded[int]{10}, + } + assert.Equal(t, "..=", r.GetJoinString()) + }) +} + +func TestRange_Bounds(t *testing.T) { + em := getCborEncoder() + dm := getCborDecoder() + + t.Run("bound included should be marshaled and unmarshaled properly", func(t *testing.T) { + bi := BoundIncluded[int]{10} + encoded, err := em.Marshal(bi) + assert.NoError(t, err) + + var decoded BoundIncluded[int] + err = dm.Unmarshal(encoded, &decoded) + assert.NoError(t, err) + assert.Equal(t, bi, decoded) + }) + + t.Run("bound excluded should be marshaled and unmarshaled properly", func(t *testing.T) { + be := BoundExcluded[int]{10} + encoded, err := em.Marshal(be) + assert.NoError(t, err) + + var decoded BoundExcluded[int] + err = dm.Unmarshal(encoded, &decoded) + assert.NoError(t, err) + assert.Equal(t, be, decoded) + }) +} + +func TestRange_CODEC(t *testing.T) { + em := getCborEncoder() + dm := getCborDecoder() + + r := Range[int, BoundIncluded[int], BoundExcluded[int]]{ + Begin: &BoundIncluded[int]{0}, + End: &BoundExcluded[int]{10}, + } + + encoded, err := em.Marshal(r) + assert.NoError(t, err) + + var decoded Range[int, BoundIncluded[int], BoundExcluded[int]] + err = dm.Unmarshal(encoded, &decoded) + assert.NoError(t, err) + assert.Equal(t, r, decoded) +} + +func TestCustomDateTime_String(t *testing.T) { + time1, err := time.Parse("2006-01-02 15:04:05", "2024-10-30 12:05:00") + assert.NoError(t, err) + + cd := CustomDateTime{time1} + assert.Equal(t, "2024-10-30T12:05:00Z", cd.String()) +} + +func TestTable_String(t *testing.T) { + table := Table("mytesttable") + assert.Equal(t, "mytesttable", table.String()) +} + +func TestCustomDuration_String(t *testing.T) { + cd := CustomDuration{time.Duration(33333333333000000)} + assert.Equal(t, "1y2w6d19h15m33s333ms", cd.String()) +} + +func TestRecordID_String(t *testing.T) { + rid := RecordID{Table: "mytesttable", ID: "121212121"} + assert.Equal(t, "mytesttable:121212121", rid.String()) +} + +func TestFormatDurationAndParseDuration(t *testing.T) { + durationStr := "1y2w6d19h15m33s333ms" + + ns, _ := ParseDuration(durationStr) + d := FormatDuration(ns) + assert.Equal(t, durationStr, d) +} + +func TestFormatDuration(t *testing.T) { + d := FormatDuration(33333333333000000) + assert.Equal(t, "1y2w6d19h15m33s333ms", d) +} diff --git a/pkg/models/datetime.go b/pkg/models/datetime.go new file mode 100644 index 0000000..e9bdd12 --- /dev/null +++ b/pkg/models/datetime.go @@ -0,0 +1,54 @@ +package models + +import ( + "fmt" + "time" + + "github.com/fxamacker/cbor/v2" + "github.com/surrealdb/surrealdb.go/pkg/constants" +) + +// CustomDateTime embeds time.Time +type CustomDateTime struct { + time.Time +} + +func (d *CustomDateTime) MarshalCBOR() ([]byte, error) { + enc := getCborEncoder() + + totalNS := d.Nanosecond() + + s := totalNS / constants.OneSecondToNanoSecond + ns := totalNS % constants.OneSecondToNanoSecond + + return enc.Marshal(cbor.Tag{ + Number: TagCustomDatetime, + Content: [2]int64{int64(s), int64(ns)}, + }) +} + +func (d *CustomDateTime) UnmarshalCBOR(data []byte) error { + dec := getCborDecoder() + + var temp [2]int64 + err := dec.Unmarshal(data, &temp) + if err != nil { + return err + } + + s := temp[0] + ns := temp[1] + + *d = CustomDateTime{time.Unix(s, ns)} + + return nil +} + +func (d *CustomDateTime) String() string { + layout := "2006-01-02T15:04:05Z" + return d.Format(layout) +} + +func (d *CustomDateTime) SurrealString() string { + return fmt.Sprintf(" '%s'", d.String()) +} diff --git a/pkg/models/duration.go b/pkg/models/duration.go index 2ba5aa3..a592a85 100644 --- a/pkg/models/duration.go +++ b/pkg/models/duration.go @@ -1,6 +1,9 @@ package models import ( + "fmt" + "regexp" + "strconv" "time" "github.com/surrealdb/surrealdb.go/pkg/constants" @@ -8,19 +11,31 @@ import ( "github.com/fxamacker/cbor/v2" ) -type CustomDuration time.Duration +const ( + nsPerNanoSecond = int64(1) + nsPerMicroSecond = 1000 * nsPerNanoSecond + nsPerMilliSecond = 1000 * nsPerMicroSecond + nsPerSecond = 1000 * nsPerMilliSecond + nsPerMinute = 60 * nsPerSecond + nsPerHour = 60 * nsPerMinute + nsPerDay = 24 * nsPerHour + nsPerWeek = 7 * nsPerDay + nsPerYear = 365 * nsPerDay +) -type CustomDurationStr string +type CustomDuration struct { + time.Duration +} func (d *CustomDuration) MarshalCBOR() ([]byte, error) { enc := getCborEncoder() - totalNS := time.Duration(*d).Nanoseconds() + totalNS := d.Nanoseconds() s := totalNS / constants.OneSecondToNanoSecond ns := totalNS % constants.OneSecondToNanoSecond return enc.Marshal(cbor.Tag{ - Number: uint64(DurationCompactTag), + Number: TagCustomDuration, Content: [2]int64{s, ns}, }) } @@ -37,7 +52,131 @@ func (d *CustomDuration) UnmarshalCBOR(data []byte) error { s := temp[0].(int64) ns := temp[1].(int64) - *d = CustomDuration(time.Duration((float64(s) * constants.OneSecondToNanoSecond) + float64(ns))) + *d = CustomDuration{time.Duration((float64(s) * constants.OneSecondToNanoSecond) + float64(ns))} return nil } + +func (d *CustomDuration) String() string { + return FormatDuration(d.Nanoseconds()) +} + +func (d *CustomDuration) ToCustomDurationString() CustomDurationString { + return CustomDurationString(d.String()) +} + +//------------------------------------------------------------------------------------------------------------------------------// + +type CustomDurationString string + +func (d *CustomDurationString) String() string { + return string(*d) +} + +func (d *CustomDurationString) ToDuration() time.Duration { + ns, err := ParseDuration(d.String()) + if err != nil { + panic(err) + } + + return time.Duration(ns) +} + +func (d *CustomDurationString) ToCustomDuration() CustomDuration { + return CustomDuration{d.ToDuration()} +} + +//------------------------------------------------------------------------------------------------------------------------------// + +func FormatDuration(ns int64) string { + years := ns / nsPerYear + ns %= nsPerYear + + weeks := ns / nsPerWeek + ns %= nsPerWeek + + days := ns / nsPerDay + ns %= nsPerDay + + hours := ns / nsPerHour + ns %= nsPerHour + + minutes := ns / nsPerMinute + ns %= nsPerMinute + + seconds := ns / nsPerSecond + ns %= nsPerSecond + + milliseconds := ns / nsPerMilliSecond + ns %= nsPerMilliSecond + + microseconds := ns / nsPerMicroSecond + ns %= nsPerMicroSecond + + result := "" + if years > 0 { + result += fmt.Sprintf("%dy", years) + } + if weeks > 0 { + result += fmt.Sprintf("%dw", weeks) + } + if days > 0 { + result += fmt.Sprintf("%dd", days) + } + if hours > 0 { + result += fmt.Sprintf("%dh", hours) + } + if minutes > 0 { + result += fmt.Sprintf("%dm", minutes) + } + if seconds > 0 { + result += fmt.Sprintf("%ds", seconds) + } + if milliseconds > 0 { + result += fmt.Sprintf("%dms", milliseconds) + } + if microseconds > 0 { + result += fmt.Sprintf("%dµs", microseconds) + } + if ns > 0 { + result += fmt.Sprintf("%dns", ns) + } + + return result +} + +func ParseDuration(duration string) (int64, error) { + // Regular expression to match the units in the duration string + re := regexp.MustCompile(`(\d+)([a-zµ]+)`) + matches := re.FindAllStringSubmatch(duration, -1) + + var totalNanoseconds int64 + + for _, match := range matches { + value, _ := strconv.ParseInt(match[1], 10, 64) + unit := match[2] + + switch unit { + case "y": + totalNanoseconds += value * nsPerYear + case "w": + totalNanoseconds += value * nsPerWeek + case "d": + totalNanoseconds += value * nsPerDay + case "h": + totalNanoseconds += value * nsPerHour + case "m": + totalNanoseconds += value * nsPerMinute + case "s": + totalNanoseconds += value * nsPerSecond + case "ms": + totalNanoseconds += value * nsPerMilliSecond + case "µs", "us": + totalNanoseconds += value * nsPerMicroSecond + case "ns": + totalNanoseconds += value * nsPerNanoSecond + } + } + + return totalNanoseconds, nil +} diff --git a/pkg/models/future.go b/pkg/models/future.go new file mode 100644 index 0000000..6548e32 --- /dev/null +++ b/pkg/models/future.go @@ -0,0 +1,15 @@ +package models + +import "fmt" + +type Future struct { + inner string +} + +func (f *Future) String() string { + return f.inner +} + +func (f *Future) SurrealString() string { + return fmt.Sprintf(" { %s }", f.String()) +} diff --git a/pkg/models/geometry.go b/pkg/models/geometry.go index cbed82e..ad4fd4a 100644 --- a/pkg/models/geometry.go +++ b/pkg/models/geometry.go @@ -21,7 +21,7 @@ func (gp *GeometryPoint) MarshalCBOR() ([]byte, error) { enc := getCborEncoder() return enc.Marshal(cbor.Tag{ - Number: uint64(GeometryPointTag), + Number: TagGeometryPoint, Content: gp.GetCoordinates(), }) } diff --git a/pkg/models/range.go b/pkg/models/range.go new file mode 100644 index 0000000..047944f --- /dev/null +++ b/pkg/models/range.go @@ -0,0 +1,149 @@ +package models + +import ( + "fmt" + "reflect" + + "github.com/fxamacker/cbor/v2" +) + +type BoundIncluded[T any] struct { + Value T +} + +func (bi *BoundIncluded[T]) MarshalCBOR() ([]byte, error) { + return getCborEncoder().Marshal(cbor.Tag{ + Number: TagBoundIncluded, + Content: bi.Value, + }) +} + +func (bi *BoundIncluded[T]) UnmarshalCBOR(data []byte) error { + var temp T + err := getCborDecoder().Unmarshal(data, &temp) + if err != nil { + return err + } + + bi.Value = temp + return nil +} + +//------------------------------------------------------------------------------------------------// + +type BoundExcluded[T any] struct { + Value T +} + +func (be *BoundExcluded[T]) MarshalCBOR() ([]byte, error) { + return getCborEncoder().Marshal(cbor.Tag{ + Number: TagBoundExcluded, + Content: be.Value, + }) +} + +func (be *BoundExcluded[T]) UnmarshalCBOR(data []byte) error { + var temp T + err := getCborDecoder().Unmarshal(data, &temp) + if err != nil { + return err + } + + be.Value = temp + return nil +} + +//------------------------------------------------------------------------------------------------// + +type Bound[T any] interface { + BoundIncluded[T] | BoundExcluded[T] +} + +type Range[T any, TBeg Bound[T], TEnd Bound[T]] struct { + Begin *TBeg + End *TEnd +} + +func (r *Range[T, TBeg, TEnd]) GetJoinString() string { + joinStr := "" + + if reflect.TypeOf(*r.Begin) == reflect.TypeOf(BoundExcluded[T]{}) { + joinStr += ">" + } + joinStr += ".." + if reflect.TypeOf(*r.End) == reflect.TypeOf(BoundIncluded[T]{}) { + joinStr += "=" + } + + return joinStr +} + +func (r *Range[T, TBeg, TEnd]) String() string { + joinStr := r.GetJoinString() + beginStr := "" + endStr := "" + + if r.Begin != nil { + beginStr = convertToString(r.Begin) + } + if r.End != nil { + endStr = convertToString(r.Begin) + } + + return fmt.Sprintf("%s%s%s", beginStr, joinStr, endStr) +} + +func (r *Range[T, TBeg, TEnd]) MarshalCBOR() ([]byte, error) { + return getCborEncoder().Marshal(cbor.Tag{ + Number: TagRange, + Content: []interface{}{r.Begin, r.End}, + }) +} + +func (r *Range[T, TBeg, TEnd]) UnmarshalCBOR(data []byte) error { + dec := getCborDecoder() + var temp [2]cbor.RawTag + err := getCborDecoder().Unmarshal(data, &temp) + if err != nil { + return err + } + + var begin TBeg + beginEnc, _ := temp[0].MarshalCBOR() + _ = dec.Unmarshal(beginEnc, &begin) + + var end TEnd + endEnc, _ := temp[1].MarshalCBOR() + _ = dec.Unmarshal(endEnc, &end) + + r.Begin = &begin + r.End = &end + return nil +} + +//---------------------------------------------------------------------------------------------------------------------// + +type RecordRangeID[T any, TBeg Bound[T], TEnd Bound[T]] struct { + Range[T, TBeg, TEnd] + Table Table +} + +func (rr *RecordRangeID[T, TBeg, TEnd]) String() string { + joinStr := rr.GetJoinString() + beginStr := "" + endStr := "" + + if rr.Begin != nil { + beginStr = convertToString(rr.Begin) + } + if rr.End != nil { + endStr = convertToString(rr.Begin) + } + + return fmt.Sprintf("%s:%s%s%s", rr.Table, beginStr, joinStr, endStr) +} + +func convertToString(v any) string { + // todo: implement + return "" +} diff --git a/pkg/models/record_id.go b/pkg/models/record_id.go index a52f31e..cb466e5 100644 --- a/pkg/models/record_id.go +++ b/pkg/models/record_id.go @@ -35,7 +35,7 @@ func (r *RecordID) MarshalCBOR() ([]byte, error) { enc := getCborEncoder() return enc.Marshal(cbor.Tag{ - Number: uint64(RecordIDTag), + Number: TagRecordID, Content: []interface{}{r.Table, r.ID}, }) } @@ -58,3 +58,7 @@ func (r *RecordID) UnmarshalCBOR(data []byte) error { func (r *RecordID) String() string { return fmt.Sprintf("%s:%s", r.Table, r.ID) } + +func (r *RecordID) SurrealString() string { + return fmt.Sprintf("r'%s'", r.String()) +} diff --git a/pkg/models/replacer.go b/pkg/models/replacer.go index 3bb1c08..0322a9b 100644 --- a/pkg/models/replacer.go +++ b/pkg/models/replacer.go @@ -11,7 +11,7 @@ func replacerBeforeEncode(value interface{}) interface{} { if valueType == reflect.TypeOf(time.Duration(0)) { oldVal := value.(time.Duration) - newValue := CustomDuration(oldVal.Nanoseconds()) + newValue := CustomDuration{oldVal} return newValue } @@ -38,9 +38,9 @@ func replacerAfterDecode(value interface{}) interface{} { valueType := reflect.TypeOf(value) valueKind := valueType.Kind() - if valueType == reflect.TypeOf(CustomDuration(0)) { + if valueType == reflect.TypeOf(CustomDuration{}) { oldVal := value.(CustomDuration) - newValue := time.Duration(oldVal) + newValue := oldVal.Duration return newValue } diff --git a/pkg/models/table.go b/pkg/models/table.go new file mode 100644 index 0000000..9068740 --- /dev/null +++ b/pkg/models/table.go @@ -0,0 +1,7 @@ +package models + +type Table string + +func (t Table) String() string { + return string(t) +} diff --git a/pkg/models/types.go b/pkg/models/types.go index bd34f03..b97078e 100644 --- a/pkg/models/types.go +++ b/pkg/models/types.go @@ -1,61 +1,10 @@ package models import ( - "time" - - "github.com/surrealdb/surrealdb.go/pkg/constants" - "github.com/fxamacker/cbor/v2" - "github.com/gofrs/uuid" ) -type TableOrRecord interface { - string | Table | RecordID | []Table | []RecordID -} - -type Table string - -// type UUID string - -// type UUIDBin []byte -type UUID struct { - uuid.UUID -} - -type Decimal string - -type CustomDateTime time.Time - -func (d *CustomDateTime) MarshalCBOR() ([]byte, error) { - enc := getCborEncoder() - - totalNS := time.Time(*d).Nanosecond() - - s := totalNS / constants.OneSecondToNanoSecond - ns := totalNS % constants.OneSecondToNanoSecond - - return enc.Marshal(cbor.Tag{ - Number: uint64(DateTimeCompactString), - Content: [2]int64{int64(s), int64(ns)}, - }) -} - -func (d *CustomDateTime) UnmarshalCBOR(data []byte) error { - dec := getCborDecoder() - - var temp [2]int64 - err := dec.Unmarshal(data, &temp) - if err != nil { - return err - } - - s := temp[0] - ns := temp[1] - - *d = CustomDateTime(time.Unix(s, ns)) - - return nil -} +type DecimalString string type CustomNil struct { } @@ -64,7 +13,7 @@ func (c *CustomNil) MarshalCBOR() ([]byte, error) { enc := getCborEncoder() return enc.Marshal(cbor.Tag{ - Number: uint64(NoneTag), + Number: TagNone, Content: nil, }) } diff --git a/pkg/models/uuid.go b/pkg/models/uuid.go new file mode 100644 index 0000000..1b35edd --- /dev/null +++ b/pkg/models/uuid.go @@ -0,0 +1,9 @@ +package models + +import "github.com/gofrs/uuid" + +type UUIDString string + +type UUID struct { + uuid.UUID +} diff --git a/types.go b/types.go index c6340ee..2773723 100644 --- a/types.go +++ b/types.go @@ -56,3 +56,7 @@ type Obj map[interface{}]interface{} type Result[T any] struct { T any } + +type TableOrRecord interface { + string | models.Table | models.RecordID | []models.Table | []models.RecordID +}