github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/dsn/dsn.go (about)

     1  package dsn
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  )
     8  
     9  // Flag is the datasource dsn structure.
    10  type Flag struct {
    11  	Username, Password, Host string
    12  	Port                     int
    13  	Database                 string
    14  }
    15  
    16  // ParseFlag parses format like user:pass@host:port/db.
    17  func ParseFlag(source string) (dc *Flag, err error) {
    18  	dc = &Flag{}
    19  	atPos := strings.LastIndex(source, "@")
    20  	if atPos < 0 {
    21  		err = fmt.Errorf("invalid source: %s, should be username:password@host:port", source)
    22  		return
    23  	}
    24  
    25  	userPart := source[:atPos]
    26  	if n := strings.IndexAny(userPart, "/:"); n > 0 {
    27  		if dc.Username = userPart[:n]; n+1 < len(userPart) {
    28  			dc.Password = userPart[n+1:]
    29  		}
    30  	} else {
    31  		dc.Username = userPart
    32  	}
    33  
    34  	if atPos+1 >= len(source) {
    35  		err = fmt.Errorf("invalid source: %s, should be username:password@host:port", source)
    36  		return
    37  	}
    38  
    39  	hostPart := source[atPos+1:]
    40  
    41  	if n := strings.LastIndex(hostPart, "/"); n > 0 {
    42  		dc.Database = hostPart[n+1:]
    43  		hostPart = hostPart[:n]
    44  	}
    45  
    46  	if n := strings.LastIndex(hostPart, ":"); n > 0 {
    47  		if dc.Host = hostPart[:n]; n+1 < len(hostPart) {
    48  			dc.Port, err = strconv.Atoi(hostPart[n+1:])
    49  			if err != nil {
    50  				err = fmt.Errorf("port %s is not a number", hostPart[n+1:])
    51  				return
    52  			}
    53  		}
    54  	} else {
    55  		dc.Host = hostPart
    56  	}
    57  
    58  	return
    59  }