-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
113 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package snowflake | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
// Snowflake represents a Discord snowflake. | ||
// See https://discord.com/developers/docs/reference | ||
// for more information. | ||
type Snowflake int64 | ||
|
||
// Nil represents an empty Snowflake. | ||
var Nil = (*Snowflake)(nil) | ||
|
||
// Zero represents the zero value for a Snowflake. | ||
var Zero = Snowflake(0) | ||
|
||
// discordEpoch is the time of the first second of 2015, in milliseconds. | ||
const discordEpoch = 1420070400000 | ||
|
||
// Parse constructs a Snowflake from s. | ||
func Parse(s string) (Snowflake, error) { | ||
if s == "" { | ||
return Zero, nil | ||
} | ||
parsed, err := strconv.ParseInt(s, 10, 0) | ||
return Snowflake(parsed), err | ||
} | ||
|
||
// FromTimestamp generates a Snowflake for the given time. | ||
func FromTimestamp(time time.Time) Snowflake { | ||
return Snowflake(time.UnixMilli()-discordEpoch) << 22 | ||
} | ||
|
||
// Timestamp returns the number of milliseconds since discordEpoch. | ||
func (s Snowflake) Timestamp() int64 { | ||
return (int64(s) >> 22) + discordEpoch | ||
} | ||
|
||
// WorkerID returns the Snowflake's worker id. | ||
func (s Snowflake) WorkerID() int64 { | ||
return (int64(s) & 0x3E0000) >> 17 | ||
} | ||
|
||
// ProcessID returns the Snowflake's process id. | ||
func (s Snowflake) ProcessID() int64 { | ||
return (int64(s) & 0x1F000) >> 12 | ||
} | ||
|
||
// Increment returns the number of id's that have | ||
// been generated on the Snowflake's process. | ||
func (s Snowflake) Increment() int64 { | ||
return int64(s) & 0xFFF | ||
} | ||
|
||
// UnmarshalJSON unmarshals data into s. | ||
func (s *Snowflake) UnmarshalJSON(data []byte) error { | ||
dec := json.NewDecoder(bytes.NewReader(data)) | ||
dec.UseNumber() | ||
|
||
var raw json.Number | ||
if err := dec.Decode(&raw); err != nil { | ||
typeErr, ok := err.(*json.UnmarshalTypeError) | ||
if ok { | ||
return UnmarshalTypeError{ | ||
value: typeErr.Value, | ||
structName: typeErr.Struct, | ||
field: typeErr.Field, | ||
typ: "int or string", | ||
} | ||
} | ||
return err | ||
} | ||
|
||
parsed, err := raw.Int64() | ||
if err == nil { | ||
*s = Snowflake(parsed) | ||
} | ||
return err | ||
} | ||
|
||
// MarshalJSON returns the JSON representation of s. | ||
func (s Snowflake) MarshalJSON() ([]byte, error) { | ||
return []byte(s.String()), nil | ||
} | ||
|
||
// String returns the string representation of s. | ||
func (s Snowflake) String() string { | ||
return strconv.FormatInt(int64(s), 10) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package snowflake | ||
|
||
import "fmt" | ||
|
||
// UnmarshalTypeError is like json.UnmarshalTypeError, but | ||
// uses a string to represent the Go value it could not be | ||
// assigned to, instead of a reflect.Type. | ||
type UnmarshalTypeError struct { | ||
value string | ||
structName string | ||
field string | ||
typ string | ||
} | ||
|
||
func (err UnmarshalTypeError) Error() string { | ||
if err.structName != "" || err.field != "" { | ||
return fmt.Sprintf("json: cannot unmarshal %s into Go struct field %s\".\"%s of type %s", err.value, err.structName, err.field, err.typ) | ||
} | ||
return fmt.Sprintf("json: cannot unmarshal %s into Go value of type %s", err.value, err.typ) | ||
} |