func (g *Geometry) Scan(src interface{}) error {
	var wkb []byte
	switch src := src.(type) {
	case []byte:
		wkb = src
	case string:
		wkb = []byte(src)
	default:
		return fmt.Errorf("unsupported src type in Scan: %T", src)
	}
	unmarshalled, err := UnmarshalWKB(wkb)
	if err != nil {
		return wrap(err, "scanning as WKB")
	}
	*g = unmarshalled
	return nil
}
Scan implements the database/sql.Scanner interface by parsing the src value
as WKB (Well Known Binary).

It constructs the resultant geometry with no ConstructionOptions. If
ConstructionOptions are needed, then the value should be scanned into a byte
slice and then UnmarshalWKB called manually (passing in the
ConstructionOptions as desired).
package geom
import (
	"database/sql/driver"
	"fmt"
	"unsafe"
)
type Geometry struct {
	gtype GeometryType
	ptr   unsafe.Pointer
}
type GeometryType int
const (
	TypeGeometryCollection GeometryType = iota
	TypePoint
	TypeLineString
	TypePolygon
	TypeMultiPoint
	TypeMultiLineString
	TypeMultiPolygon
)
func (t GeometryType) String() string {
	switch t {
	case TypeGeometryCollection:
		return "GeometryCollection"
	case TypePoint:
		return "Point"
	case TypeLineString:
		return "LineString"
	case TypePolygon:
		return "Polygon"
	case TypeMultiPoint:
		return "MultiPoint"
	case TypeMultiLineString:
		return "MultiLineString"
	case TypeMultiPolygon:
		return "MultiPolygon"
	default:
		return "invalid"
	}
}
func (g Geometry) Type() GeometryType {
	switch g.gtype {
	case TypeGeometryCollection:
		return g.AsGeometryCollection().Type()
	case TypePoint:
		return g.AsPoint().Type()
	case TypeLineString:
		return g.AsLineString().Type()
	case TypePolygon:
		return g.AsPolygon().Type()
	case TypeMultiPoint:
		return g.AsMultiPoint().Type()
	case TypeMultiLineString:
		return g.AsMultiLineString().Type()
	case TypeMultiPolygon:
		return g.AsMultiPolygon().Type()
	default:
		panic("unknown geometry: " + g.gtype.String())
	}
}
func (g Geometry) IsGeometryCollection() bool { return g.gtype == TypeGeometryCollection }
func (g Geometry) IsPoint() bool { return g.gtype == TypePoint }
func (g Geometry) IsLineString() bool { return g.gtype == TypeLineString }
func (g Geometry) IsPolygon() bool { return g.gtype == TypePolygon }
func (g Geometry) IsMultiPoint() bool { return g.gtype == TypeMultiPoint }
func (g Geometry) IsMultiLineString() bool { return g.gtype == TypeMultiLineString }
func (g Geometry) IsMultiPolygon() bool { return g.gtype == TypeMultiPolygon }
func (g Geometry) check(gtype GeometryType) {
	if g.gtype != gtype {
		panic(fmt.Sprintf("called As%s on Geometry containing %s", gtype, g.gtype))
	}
}
func (g Geometry) AsGeometryCollection() GeometryCollection {
	g.check(TypeGeometryCollection)
	if g.ptr == nil {
		return GeometryCollection{}
	}
	return *(*GeometryCollection)(g.ptr)
}
func (g Geometry) AsPoint() Point {
	g.check(TypePoint)
	return *(*Point)(g.ptr)
}
func (g Geometry) AsLineString() LineString {
	g.check(TypeLineString)
	return *(*LineString)(g.ptr)
}
func (g Geometry) AsPolygon() Polygon {
	g.check(TypePolygon)
	return *(*Polygon)(g.ptr)
}
func (g Geometry) AsMultiPoint() MultiPoint {
	g.check(TypeMultiPoint)
	return *(*MultiPoint)(g.ptr)
}
func (g Geometry) AsMultiLineString() MultiLineString {
	g.check(TypeMultiLineString)
	return *(*MultiLineString)(g.ptr)
}
func (g Geometry) AsMultiPolygon() MultiPolygon {
	g.check(TypeMultiPolygon)
	return *(*MultiPolygon)(g.ptr)
}
func (g Geometry) AsText() string {
	switch g.gtype {
	case TypeGeometryCollection:
		return g.AsGeometryCollection().AsText()
	case TypePoint:
		return g.AsPoint().AsText()
	case TypeLineString:
		return g.AsLineString().AsText()
	case TypePolygon:
		return g.AsPolygon().AsText()
	case TypeMultiPoint:
		return g.AsMultiPoint().AsText()
	case TypeMultiLineString:
		return g.AsMultiLineString().AsText()
	case TypeMultiPolygon:
		return g.AsMultiPolygon().AsText()
	default:
		panic("unknown geometry: " + g.gtype.String())
	}
}
func (g Geometry) MarshalJSON() ([]byte, error) {
	switch g.gtype {
	case TypeGeometryCollection:
		return g.AsGeometryCollection().MarshalJSON()
	case TypePoint:
		return g.AsPoint().MarshalJSON()
	case TypeLineString:
		return g.AsLineString().MarshalJSON()
	case TypePolygon:
		return g.AsPolygon().MarshalJSON()
	case TypeMultiPoint:
		return g.AsMultiPoint().MarshalJSON()
	case TypeMultiLineString:
		return g.AsMultiLineString().MarshalJSON()
	case TypeMultiPolygon:
		return g.AsMultiPolygon().MarshalJSON()
	default:
		panic("unknown geometry: " + g.gtype.String())
	}
}
func (g *Geometry) UnmarshalJSON(p []byte) error {
	geom, err := UnmarshalGeoJSON(p)
	if err != nil {
		return err
	}
	*g = geom
	return nil
}
func (g Geometry) AppendWKT(dst []byte) []byte {
	switch g.gtype {
	case TypeGeometryCollection:
		return (*GeometryCollection)(g.ptr).AppendWKT(dst)
	case TypePoint:
		return (*Point)(g.ptr).AppendWKT(dst)
	case TypeLineString:
		return (*LineString)(g.ptr).AppendWKT(dst)
	case TypePolygon:
		return (*Polygon)(g.ptr).AppendWKT(dst)
	case TypeMultiPoint:
		return (*MultiPoint)(g.ptr).AppendWKT(dst)
	case TypeMultiLineString:
		return (*MultiLineString)(g.ptr).AppendWKT(dst)
	case TypeMultiPolygon:
		return (*MultiPolygon)(g.ptr).AppendWKT(dst)
	default:
		panic("unknown geometry: " + g.gtype.String())
	}
}
func (g Geometry) AsBinary() []byte {
	return g.AppendWKB(nil)
}
func (g Geometry) AppendWKB(dst []byte) []byte {
	switch g.gtype {
	case TypeGeometryCollection:
		return g.AsGeometryCollection().AppendWKB(dst)
	case TypePoint:
		return g.AsPoint().AppendWKB(dst)
	case TypeLineString:
		return g.AsLineString().AppendWKB(dst)
	case TypePolygon:
		return g.AsPolygon().AppendWKB(dst)
	case TypeMultiPoint:
		return g.AsMultiPoint().AppendWKB(dst)
	case TypeMultiLineString:
		return g.AsMultiLineString().AppendWKB(dst)
	case TypeMultiPolygon:
		return g.AsMultiPolygon().AppendWKB(dst)
	default:
		panic("unknown geometry: " + g.gtype.String())
	}
}
func (g Geometry) Value() (driver.Value, error) {
	return g.AsBinary(), nil
}