snowflake

package module
v4.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2021 License: GPL-3.0 Imports: 4 Imported by: 3

README

Snowflake GoDoc codecov Go Report Card Test Coverage

forthebadgeforthebadge

This lib supports signed numbers, but will convert them to uint64.

Does not hold functionality to connect a snowflake service, nor generating snowflakes. But rather parsing the snowflakes from JSON only. The default behaviour is to parse Discord snowflakes, but build constraints exists to handle twitter snowflakes as well. Note that there also exist DateByEpoch to which you can pass any desired epoch to affect the date parsing.

For module usage you must utilise the suffix found in the go.mod file (/v2 for v2.x.x releases, /v3 for v3.x.x releases, etc.).

Usage:

Note: if you are against dot imports, which I can understand, instead of writing snowflake.Snowflake, you can write snowflake.ID. ID is just an alias for Snowflake.

import . "github.com/andersfylling/snowflake"

type DiscordRole struct {
    ID          Snowflake    `json:"id"`
    Name        string       `json:"name"`
    Managed     bool         `json:"managed"`
    Mentionable bool         `json:"mentionable"`
    Hoist       bool         `json:"hoist"`
    Color       int          `json:"color"`
    Position    int          `json:"position"`
    Permissions uint64       `json:"permissions"`
}

If you're creating an API that sends JSON to a multiple different language clients, some might not be able to process uint64, such as javascript. To support both uint64 and string use the JSON struct included:

import . "github.com/andersfylling/snowflake"

type DiscordRole struct {
    *SnowflakeJSON           `json:"snowflake"`
    Name        string       `json:"name"`
    Managed     bool         `json:"managed"`
    Mentionable bool         `json:"mentionable"`
    Hoist       bool         `json:"hoist"`
    Color       int          `json:"color"`
    Position    int          `json:"position"`
    Permissions uint64       `json:"permissions"`
}

This adds two fields: ID and IDStr. Where the first is of a snowflake.ID(uint64), and the second is a string. This creates the JSON format (IDs only. Where the dots represents the remaining DiscordRole fields):

{
    "snowflake": {
          "id": 74895735435643,
          "id_str": "74895735435643",
    }
}

Now an alternative is to send only the string version by adding ,string to the json tag. Since Snowflake utilizes a custom Marshaler, this won't function. if you want to support 32bit languages, you must use the SnowflakeJSON as mentioned above. You can also extract a SnowflakeJSON from a Snowflake by calling Snowflake.JSONStruct().

Build constraints

if you want the Snowflake.Date() method to parse snowflakes based on the twitter epoch, you can do go build -tags=snowflake_twitter. The default behaviour will use the Discord epoch.

Benchmarks
BenchmarkUnmarshalJSON/string-8                        50000000	        24.70 ns/op
BenchmarkUnmarshalJSON/uint64-a-8                     300000000	         4.17 ns/op
BenchmarkUnmarshalJSON/uint64-b-8                      20000000	        77.30 ns/op

BenchmarkUnmarshalJSON/string-struct-8                  3000000	       500.00 ns/op
BenchmarkUnmarshalJSON/snowflake-struct-8               3000000	       476.00 ns/op

BenchmarkUnmarshal_snowflakeStrategies/dereference-8  100000000	        15.40 ns/op
BenchmarkUnmarshal_snowflakeStrategies/tmp-var-8      100000000	        11.00 ns/op

In the first 3 tests, I test out the convertion strategy directly.

  1. string: byte slice is copied by calling dst = string(src)
  2. uint64-a: a custom converted (loop) is used
  3. uint64-b: strconv.ParseUint is used

In the next 2 tests, I call json.Unmarshal to see how it will perform in real life.

  1. a struct with ID string 'json:"snowflake"'
  2. a struct with ID Snowflake 'json:"snowflake"', which utilises the custom loop found in #2

These last tests simply regards optimazations of the current custom loop, just as removing dereference. (The UnmarshalJSON method is called here which is why it slower than #2).

  1. using dereference to update the snowflake during loop
  2. using a local var during the loop, then updating the snowflake when finishing with no error

Documentation

Index

Constants

View Source
const (
	EpochDiscord uint64 = 1420070400000
	EpochTwitter uint64 = 1288834974657
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ID

type ID = Snowflake

type Snowflake

type Snowflake uint64

Snowflake twitter snowflake design

func GetSnowflake

func GetSnowflake(v interface{}) (s Snowflake, err error)

func NewSnowflake

func NewSnowflake(id uint64) Snowflake

NewID creates a new Snowflake Snowflake from a uint64.

func ParseSnowflakeString

func ParseSnowflakeString(v string) Snowflake

ParseSnowflakeString interprets a string with a decimal number.

Note that in contrast to ParseUint, this function assumes the given string is
always valid and thus will panic rather than return an error.
This should only be used on checks that can be done at compile time,
unless you want to trust other modules to returns valid data.

func ParseSnowflakeUint

func ParseSnowflakeUint(v string, base int) (Snowflake, error)

ParseUint converts a string and given base to a Snowflake

func (Snowflake) Date

func (s Snowflake) Date() time.Time

func (Snowflake) DateByEpoch

func (s Snowflake) DateByEpoch(epoch uint64) time.Time

func (Snowflake) HexPrettyString

func (s Snowflake) HexPrettyString() string

HexPrettyString converts the Snowflake into a hexadecimal string with the hex prefix 0x

func (Snowflake) HexString

func (s Snowflake) HexString() string

HexString converts the Snowflake into a hexadecimal string

func (Snowflake) IsZero

func (s Snowflake) IsZero() bool

IsZero since snowflake exists of several parts, including a timestamp,

I assume a valid snowflake Snowflake is never 0.

func (Snowflake) JSONStruct

func (s Snowflake) JSONStruct() *SnowflakeJSON

JSONStruct returns a struct that can be embedded in other structs.

This is useful if you have a API server, since js can't parse uint64.
Therefore there must a snowflake Snowflake string.

func (Snowflake) MarshalBinary

func (s Snowflake) MarshalBinary() (data []byte, err error)

MarshalBinary create a binary literal representation as a string

func (Snowflake) MarshalJSON

func (s Snowflake) MarshalJSON() (data []byte, err error)

func (Snowflake) MarshalText

func (s Snowflake) MarshalText() (text []byte, err error)

func (Snowflake) String

func (s Snowflake) String() string

String returns the decimal representation of the snowflake Snowflake.

func (*Snowflake) UnmarshalBinary

func (s *Snowflake) UnmarshalBinary(text []byte) (err error)

func (*Snowflake) UnmarshalJSON

func (s *Snowflake) UnmarshalJSON(data []byte) (err error)

func (*Snowflake) UnmarshalText

func (s *Snowflake) UnmarshalText(text []byte) (err error)

func (Snowflake) Valid

func (s Snowflake) Valid() bool

Valid makes sure the snowflake is after the fixed epoch

type SnowflakeJSON

type SnowflakeJSON struct {
	ID    Snowflake `json:"id"`
	IDStr string    `json:"id_str"`
}

JSON can be useful when sending the snowflake Snowflake by a json API

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL