You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: dsn.go
    path of file: ./repos/tegola/vendor/github.com/SAP/go-hdb/driver
    
    the code of the file until where you have to start completion: package driver

import (
	"errors"
	"fmt"
	"net/url"
	"strconv"
	"time"
)

// DSN parameters. For parameter client locale see http://help.sap.com/hana/SAP_HANA_SQL_Command_Network_Protocol_Reference_en.pdf.
const (
	DSNDefaultSchema = "defaultSchema" // Database default schema.
	DSNTimeout       = "timeout"       // Driver side connection timeout in seconds.
	DSNPingInterval  = "pingInterval"  // Connection ping interval in seconds.
)

/*
DSN TLS parameters.
For more information please see https://golang.org/pkg/crypto/tls/#Config.
For more flexibility in TLS configuration please see driver.Connector.
*/
const (
	DSNTLSRootCAFile         = "TLSRootCAFile"         // Path,- filename to root certificate(s).
	DSNTLSServerName         = "TLSServerName"         // ServerName to verify the hostname.
	DSNTLSInsecureSkipVerify = "TLSInsecureSkipVerify" // Controls whether a client verifies the server's certificate chain and host name.
)

// TLSPrms is holding the TLS parameters of a DSN struct
    
func parseDSN(s string) (*DSN, error) {
	if s == "" {
		return nil, &ParseError{s: "invalid parameter - DSN is empty"}
	}

	u, err := url.Parse(s)
	if err != nil {
		return nil, &ParseError{err: err}
	}

	dsn := &DSN{host: u.Host}
	if u.User != nil {
		dsn.username = u.User.Username()
		password, _ := u.User.Password()
		dsn.password = password
	}

	for k, v := range u.Query() {
		switch k {

		default:
			return nil, parameterNotSupportedError(k)

		case DSNDefaultSchema:
			if len(v) != 1 {
				return nil, invalidNumberOfParametersError(k, len(v), 1)
			}
			dsn.defaultSchema = v[0]

		case DSNTimeout:
			if len(v) != 1 {
				return nil, invalidNumberOfParametersError(k, len(v), 1)
			}
			t, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, parseError(k, v[0])
			}
			dsn.timeout = time.Duration(t) * time.Second

		case DSNPingInterval:
			if len(v) != 1 {
				return nil, invalidNumberOfParametersError(k, len(v), 1)
			}
			t, err := strconv.Atoi(v[0])
			if err != nil {
				return nil, parseError(k, v[0])
			}
			dsn.pingInterval = time.Duration(t) * time.Second

		case DSNTLSServerName:
			if len(v) != 1 {
				return nil, invalidNumberOfParametersError(k, len(v), 1)
			}
			if dsn.tls == nil {
				dsn.tls = &TLSPrms{}
			}
			dsn.tls.ServerName = v[0]

		case DSNTLSInsecureSkipVerify:
			if len(v) > 1 {
				return nil, invalidNumberOfParametersRangeError(k, len(v), 0, 1)
			}
			b := true
			if len(v) > 0 && v[0] != "" {
				b, err = strconv.ParseBool(v[0])
				if err != nil {
					return nil, parseError(k, v[0])
				}
			}
			if dsn.tls == nil {
				dsn.tls = &TLSPrms{}
			}
			dsn.tls.InsecureSkipVerify = b

		case DSNTLSRootCAFile:
			if len(v) == 0 {
				return nil, invalidNumberOfParametersMinError(k, len(v), 1)
			}
			if dsn.tls == nil {
				dsn.tls = &TLSPrms{}
			}
			dsn.tls.RootCAFiles = v
		}
	}
	return dsn, nil
}