package pgtype import ( "database/sql/driver" "encoding/binary" "fmt" "github.com/jackc/pgio" ) type <%= multirange_type %> struct { Ranges []<%= range_type %> Status Status } func (dst *<%= multirange_type %>) Set(src interface{}) error { //untyped nil and typed nil interfaces are different if src == nil { *dst = <%= multirange_type %>{Status: Null} return nil } switch value := src.(type) { case <%= multirange_type %>: *dst = value case *<%= multirange_type %>: *dst = *value case string: return dst.DecodeText(nil, []byte(value)) case []<%= range_type %>: if value == nil { *dst = <%= multirange_type %>{Status: Null} } else if len(value) == 0 { *dst = <%= multirange_type %>{Status: Present} } else { elements := make([]<%= range_type %>, len(value)) for i := range value { if err := elements[i].Set(value[i]); err != nil { return err } } *dst = <%= multirange_type %>{ Ranges: elements, Status: Present, } } case []*<%= range_type %>: if value == nil { *dst = <%= multirange_type %>{Status: Null} } else if len(value) == 0 { *dst = <%= multirange_type %>{Status: Present} } else { elements := make([]<%= range_type %>, len(value)) for i := range value { if err := elements[i].Set(value[i]); err != nil { return err } } *dst = <%= multirange_type %>{ Ranges: elements, Status: Present, } } default: return fmt.Errorf("cannot convert %v to <%= multirange_type %>", src) } return nil } func (dst <%= multirange_type %>) Get() interface{} { switch dst.Status { case Present: return dst case Null: return nil default: return dst.Status } } func (src *<%= multirange_type %>) AssignTo(dst interface{}) error { return fmt.Errorf("cannot assign %v to %T", src, dst) } func (dst *<%= multirange_type %>) DecodeText(ci *ConnInfo, src []byte) error { if src == nil { *dst = <%= multirange_type %>{Status: Null} return nil } utmr, err := ParseUntypedTextMultirange(string(src)) if err != nil { return err } var elements []<%= range_type %> if len(utmr.Elements) > 0 { elements = make([]<%= range_type %>, len(utmr.Elements)) for i, s := range utmr.Elements { var elem <%= range_type %> elemSrc := []byte(s) err = elem.DecodeText(ci, elemSrc) if err != nil { return err } elements[i] = elem } } *dst = <%= multirange_type %>{Ranges: elements, Status: Present} return nil } func (dst *<%= multirange_type %>) DecodeBinary(ci *ConnInfo, src []byte) error { if src == nil { *dst = <%= multirange_type %>{Status: Null} return nil } rp := 0 numElems := int(binary.BigEndian.Uint32(src[rp:])) rp += 4 if numElems == 0 { *dst = <%= multirange_type %>{Status: Present} return nil } elements := make([]<%= range_type %>, numElems) for i := range elements { elemLen := int(int32(binary.BigEndian.Uint32(src[rp:]))) rp += 4 var elemSrc []byte if elemLen >= 0 { elemSrc = src[rp : rp+elemLen] rp += elemLen } err := elements[i].DecodeBinary(ci, elemSrc) if err != nil { return err } } *dst = <%= multirange_type %>{Ranges: elements, Status: Present} return nil } func (src <%= multirange_type %>) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) { switch src.Status { case Null: return nil, nil case Undefined: return nil, errUndefined } buf = append(buf, '{') inElemBuf := make([]byte, 0, 32) for i, elem := range src.Ranges { if i > 0 { buf = append(buf, ',') } elemBuf, err := elem.EncodeText(ci, inElemBuf) if err != nil { return nil, err } if elemBuf == nil { return nil, fmt.Errorf("multi-range does not allow null range") } else { buf = append(buf, string(elemBuf)...) } } buf = append(buf, '}') return buf, nil } func (src <%= multirange_type %>) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) { switch src.Status { case Null: return nil, nil case Undefined: return nil, errUndefined } buf = pgio.AppendInt32(buf, int32(len(src.Ranges))) for i := range src.Ranges { sp := len(buf) buf = pgio.AppendInt32(buf, -1) elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf) if err != nil { return nil, err } if elemBuf != nil { buf = elemBuf pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4)) } } return buf, nil } // Scan implements the database/sql Scanner interface. func (dst *<%= multirange_type %>) Scan(src interface{}) error { if src == nil { return dst.DecodeText(nil, nil) } switch src := src.(type) { case string: return dst.DecodeText(nil, []byte(src)) case []byte: srcCopy := make([]byte, len(src)) copy(srcCopy, src) return dst.DecodeText(nil, srcCopy) } return fmt.Errorf("cannot scan %T", src) } // Value implements the database/sql/driver Valuer interface. func (src <%= multirange_type %>) Value() (driver.Value, error) { return EncodeValueText(src) }