Mercurial > gemma
view pkg/models/common.go @ 5675:b8da63027b48 sr-v2
Started to separate mesh serialisation in different files.
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sat, 10 Feb 2024 22:22:03 +0100 |
parents | 1222b777f51f |
children | 6270951dda28 |
line wrap: on
line source
// This is Free Software under GNU Affero General Public License v >= 3.0 // without warranty, see README.md and license for details. // // SPDX-License-Identifier: AGPL-3.0-or-later // License-Filename: LICENSES/AGPL-3.0.txt // // Copyright (C) 2018 by via donau // – Österreichische Wasserstraßen-Gesellschaft mbH // Software engineering by Intevation GmbH // // Author(s): // * Sascha L. Teichmann <sascha.teichmann@intevation.de> package models import ( "database/sql/driver" "encoding/json" "errors" "fmt" "regexp" "strings" "time" "gemma.intevation.de/gemma/pkg/common" ) var ( errNoString = errors.New("not a string") errNoByteSlice = errors.New("not a byte slice") ) // WGS84 is the EPSG of the World Geodetic System 1984. const WGS84 = 4326 type ( // Date is the common on-wire date represention. Date struct{ time.Time } // Time is the common on-wire time represention. Time struct{ time.Time } // Country is a valid country 2 letter code. Country string // UniqueCountries is a list of unique countries. UniqueCountries []Country // SafePath should only contain chars that directory traversal safe. SafePath string ) // MarshalJSON implements the json.Marshaler interface. func (d Date) MarshalJSON() ([]byte, error) { return json.Marshal(d.Format(common.DateFormat)) } // UnmarshalJSON implements the json.Unmarshaler interface. func (d *Date) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } d2, err := time.Parse(common.DateFormat, s) if err == nil { *d = Date{d2} } return err } // MarshalJSON implements the json.Marshaler interface. func (t Time) MarshalJSON() ([]byte, error) { return json.Marshal(t.Format(common.TimeFormat)) } // UnmarshalJSON implements the json.Unmarshaler interface. func (t *Time) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } t2, err := time.Parse(common.TimeFormat, s) if err == nil { *t = Time{t2} } return err } var ( validCountries = []string{ "AT", "BG", "DE", "HU", "HR", "MD", "RO", "RS", "SK", "UA", } ) // Valid checks if the given country is a known one. func (c Country) Valid() bool { for _, v := range validCountries { if string(c) == v { return true } } return false } // UnmarshalJSON ensures that the given string forms a valid // two letter country code. func (c *Country) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } u := strings.ToUpper(s) for _, v := range validCountries { if v == u { *c = Country(v) return nil } } return fmt.Errorf("'%s' is not a valid country", s) } // Value implements the driver.Valuer interface. func (c Country) Value() (driver.Value, error) { return string(c), nil } // Scan implements the sql.Scanner interfaces. func (c *Country) Scan(src interface{}) (err error) { if s, ok := src.(string); ok { *c = Country(s) } else { err = errNoString } return } // UnmarshalJSON implements the json.Unmarshaler interface. func (uc *UniqueCountries) UnmarshalJSON(data []byte) error { var countries []Country if err := json.Unmarshal(data, &countries); err != nil { return err } unique := map[Country]struct{}{} for _, c := range countries { if _, found := unique[c]; found { return fmt.Errorf("country '%s' is not unique", string(c)) } unique[c] = struct{}{} } *uc = countries return nil } func (uc UniqueCountries) String() string { var b strings.Builder for i, c := range uc { if i > 0 { b.WriteString(", ") } b.WriteString(string(c)) } return b.String() } // SafePathExp is used to check if a path consists only // of harmless runes. const SafePathExp = "[a-zA-Z0-9_-]+" var safePathRegExp = regexp.MustCompile("^" + SafePathExp + "$") // Valid checks is the given path is safe. func (sp SafePath) Valid() bool { return safePathRegExp.MatchString(string(sp)) } // UnmarshalJSON ensures that the given string only consist // of runes that are directory traversal safe. func (sp *SafePath) UnmarshalJSON(data []byte) error { var s string if err := json.Unmarshal(data, &s); err != nil { return err } if c := SafePath(s); c.Valid() { *sp = c return nil } return fmt.Errorf("'%s' is not a safe path", s) }