github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/accounts/url.go (about)

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