github.com/luckypickle/go-ethereum-vet@v1.14.2/accounts/url.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package accounts 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "strings" 24 ) 25 26 // URL represents the canonical identification URL of a wallet or account. 27 // 28 // It is a simplified version of url.URL, with the important limitations (which 29 // are considered features here) that it contains value-copyable components only, 30 // as well as that it doesn't do any URL encoding/decoding of special characters. 31 // 32 // The former is important to allow an account to be copied without leaving live 33 // references to the original version, whereas the latter is important to ensure 34 // one single canonical form opposed to many allowed ones by the RFC 3986 spec. 35 // 36 // As such, these URLs should not be used outside of the scope of an Ethereum 37 // wallet or account. 38 type URL struct { 39 Scheme string // Protocol scheme to identify a capable account backend 40 Path string // Path for the backend to identify a unique entity 41 } 42 43 // parseURL converts a user supplied URL into the accounts specific structure. 44 func parseURL(url string) (URL, error) { 45 parts := strings.Split(url, "://") 46 if len(parts) != 2 || parts[0] == "" { 47 return URL{}, errors.New("protocol scheme missing") 48 } 49 return URL{ 50 Scheme: parts[0], 51 Path: parts[1], 52 }, nil 53 } 54 55 // String implements the stringer interface. 56 func (u URL) String() string { 57 if u.Scheme != "" { 58 return fmt.Sprintf("%s://%s", u.Scheme, u.Path) 59 } 60 return u.Path 61 } 62 63 // TerminalString implements the log.TerminalStringer interface. 64 func (u URL) TerminalString() string { 65 url := u.String() 66 if len(url) > 32 { 67 return url[:31] + "…" 68 } 69 return url 70 } 71 72 // MarshalJSON implements the json.Marshaller interface. 73 func (u URL) MarshalJSON() ([]byte, error) { 74 return json.Marshal(u.String()) 75 } 76 77 // UnmarshalJSON parses url. 78 func (u *URL) UnmarshalJSON(input []byte) error { 79 var textURL string 80 err := json.Unmarshal(input, &textURL) 81 if err != nil { 82 return err 83 } 84 url, err := parseURL(textURL) 85 if err != nil { 86 return err 87 } 88 u.Scheme = url.Scheme 89 u.Path = url.Path 90 return nil 91 } 92 93 // Cmp compares x and y and returns: 94 // 95 // -1 if x < y 96 // 0 if x == y 97 // +1 if x > y 98 // 99 func (u URL) Cmp(url URL) int { 100 if u.Scheme == url.Scheme { 101 return strings.Compare(u.Path, url.Path) 102 } 103 return strings.Compare(u.Scheme, url.Scheme) 104 }