summaryrefslogtreecommitdiffstats
path: root/pkg/types/binary.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/types/binary.go')
-rw-r--r--pkg/types/binary.go137
1 files changed, 137 insertions, 0 deletions
diff --git a/pkg/types/binary.go b/pkg/types/binary.go
new file mode 100644
index 0000000..00a5417
--- /dev/null
+++ b/pkg/types/binary.go
@@ -0,0 +1,137 @@
+package types
+
+import (
+ "bytes"
+ "database/sql"
+ "database/sql/driver"
+ "encoding"
+ "encoding/hex"
+ "encoding/json"
+ "github.com/icinga/icingadb/internal"
+ "github.com/icinga/icingadb/pkg/contracts"
+ "github.com/pkg/errors"
+)
+
+// Binary nullable byte string. Hex as JSON.
+type Binary []byte
+
+// nullBinary for validating whether a Binary is valid.
+var nullBinary Binary
+
+// Equal returns whether the binaries are the same length and
+// contain the same bytes.
+func (binary Binary) Equal(equaler contracts.Equaler) bool {
+ b, ok := equaler.(Binary)
+ if !ok {
+ panic("bad Binary type assertion")
+ }
+
+ return bytes.Equal(binary, b)
+}
+
+// Valid returns whether the Binary is valid.
+func (binary Binary) Valid() bool {
+ return !bytes.Equal(binary, nullBinary)
+}
+
+// String returns the hex string representation form of the Binary.
+func (binary Binary) String() string {
+ return hex.EncodeToString(binary)
+}
+
+// MarshalText implements a custom marhsal function to encode
+// the Binary as hex. MarshalText implements the
+// encoding.TextMarshaler interface.
+func (binary Binary) MarshalText() ([]byte, error) {
+ return []byte(binary.String()), nil
+}
+
+// UnmarshalText implements a custom unmarshal function to decode
+// hex into a Binary. UnmarshalText implements the
+// encoding.TextUnmarshaler interface.
+func (binary *Binary) UnmarshalText(text []byte) error {
+ b := make([]byte, hex.DecodedLen(len(text)))
+ _, err := hex.Decode(b, text)
+ if err != nil {
+ return internal.CantDecodeHex(err, string(text))
+ }
+ *binary = b
+
+ return nil
+}
+
+// MarshalJSON implements a custom marshal function to encode the Binary
+// as a hex string. MarshalJSON implements the json.Marshaler interface.
+// Supports JSON null.
+func (binary Binary) MarshalJSON() ([]byte, error) {
+ if !binary.Valid() {
+ return nil, nil
+ }
+
+ return internal.MarshalJSON(binary.String())
+}
+
+// UnmarshalJSON implements a custom unmarshal function to decode
+// a JSON hex string into a Binary. UnmarshalJSON implements the
+// json.Unmarshaler interface. Supports JSON null.
+func (binary *Binary) UnmarshalJSON(data []byte) error {
+ if string(data) == "null" || len(data) == 0 {
+ return nil
+ }
+
+ var s string
+ if err := internal.UnmarshalJSON(data, &s); err != nil {
+ return err
+ }
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ return internal.CantDecodeHex(err, s)
+ }
+ *binary = b
+
+ return nil
+}
+
+// Scan implements the sql.Scanner interface.
+// Supports SQL NULL.
+func (binary *Binary) Scan(src interface{}) error {
+ switch src := src.(type) {
+ case nil:
+ return nil
+
+ case []byte:
+ if len(src) == 0 {
+ return nil
+ }
+
+ b := make([]byte, len(src))
+ copy(b, src)
+ *binary = b
+
+ default:
+ return errors.Errorf("unable to scan type %T into Binary", src)
+ }
+
+ return nil
+}
+
+// Value implements the driver.Valuer interface.
+// Supports SQL NULL.
+func (binary Binary) Value() (driver.Value, error) {
+ if !binary.Valid() {
+ return nil, nil
+ }
+
+ return []byte(binary), nil
+}
+
+// Assert interface compliance.
+var (
+ _ contracts.ID = (*Binary)(nil)
+ _ encoding.TextMarshaler = (*Binary)(nil)
+ _ encoding.TextUnmarshaler = (*Binary)(nil)
+ _ json.Marshaler = (*Binary)(nil)
+ _ json.Unmarshaler = (*Binary)(nil)
+ _ sql.Scanner = (*Binary)(nil)
+ _ driver.Valuer = (*Binary)(nil)
+)