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: service.go
    path of file: ./repos/azure-sdk-for-go/sdk/storage/azblob/sas
    
    the code of the file until where you have to start completion: //go:build go1.18
// +build go1.18

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package sas

import (
	"bytes"
	"errors"
	"fmt"
	"strings"
	"time"

	"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/internal/exported"
)

// BlobSignatureValues is used to generate a Shared Access Signature (SAS) for an Azure Storage container or blob.
// For more information on creating service sas, see https://docs.microsoft.com/rest/api/storageservices/constructing-a-service-sas
// For more information on creating user delegation sas, see https://docs.microsoft.com/rest/api/storageservices/create-user-delegation-sas
type BlobSignatureValues struct {
	Version              string    `param:"sv"`  // If not specified, this defaults to Version
	Protocol             Protocol  `param:"spr"` // See the Protocol* constants
	StartTime            time.Time `param:"st"`  // Not specified if IsZero
	ExpiryTime           time.Time `param:"se"`  // Not specified if IsZero
	SnapshotTime         time.Time
	Permissions          string  `param:"sp"` // Create by initializing ContainerPermissions or BlobPermissions and then call String()
	IPRange              IPRange `param:"sip"`
	Identifier           string  `param:"si"`
	ContainerName        string
	BlobName             string // Use "" to create a Container SAS
	Directory            string // Not nil for a directory SAS (ie sr=d)
	CacheControl         string // rscc
	ContentDisposition   string // rscd
	ContentEncoding      string // rsce
	ContentLanguage      string // rscl
	ContentType          string // rsct
	BlobVersion          string // sr=bv
	AuthorizedObjectID   string // saoid
	UnauthorizedObjectID string // suoid
	CorrelationID        string // scid
	EncryptionScope      string `param:"ses"`
}

func getDirectoryDepth(path string) string {
	if path == "" {
		return ""
	}
	return fmt.Sprint(strings.Count(path, "/") + 1)
}

// SignWithSharedKey uses an account's Sh
    
func (v BlobSignatureValues) SignWithUserDelegation(userDelegationCredential *UserDelegationCredential) (QueryParameters, error) {
	if userDelegationCredential == nil {
		return QueryParameters{}, fmt.Errorf("cannot sign SAS query without User Delegation Key")
	}

	if v.ExpiryTime.IsZero() || v.Permissions == "" {
		return QueryParameters{}, errors.New("user delegation SAS is missing at least one of these: ExpiryTime or Permissions")
	}

	// Parse the resource
	resource := "c"
	if !v.SnapshotTime.IsZero() {
		resource = "bs"
	} else if v.BlobVersion != "" {
		resource = "bv"
	} else if v.Directory != "" {
		resource = "d"
		v.BlobName = ""
	} else if v.BlobName == "" {
		// do nothing
	} else {
		resource = "b"
	}
	// make sure the permission characters are in the correct order
	if resource == "c" {
		perms, err := parseContainerPermissions(v.Permissions)
		if err != nil {
			return QueryParameters{}, err
		}
		v.Permissions = perms.String()
	} else {
		perms, err := parseBlobPermissions(v.Permissions)
		if err != nil {
			return QueryParameters{}, err
		}
		v.Permissions = perms.String()
	}

	if v.Version == "" {
		v.Version = Version
	}
	startTime, expiryTime, snapshotTime := formatTimesForSigning(v.StartTime, v.ExpiryTime, v.SnapshotTime)

	udk := exported.GetUDKParams(userDelegationCredential)

	udkStart, udkExpiry, _ := formatTimesForSigning(*udk.SignedStart, *udk.SignedExpiry, time.Time{})

	stringToSign := strings.Join([]string{
		v.Permissions,
		startTime,
		expiryTime,
		getCanonicalName(exported.GetAccountName(userDelegationCredential), v.ContainerName, v.BlobName, v.Directory),
		*udk.SignedOID,
		*udk.SignedTID,
		udkStart,
		udkExpiry,
		*udk.SignedService,
		*udk.SignedVersion,
		v.AuthorizedObjectID,
		v.UnauthorizedObjectID,
		v.CorrelationID,
		v.IPRange.String(),
		string(v.Protocol),
		v.Version,
		resource,
		snapshotTime, // signed timestamp
		v.EncryptionScope,
		v.CacheControl,       // rscc
		v.ContentDisposition, // rscd
		v.ContentEncoding,    // rsce
		v.ContentLanguage,    // rscl
		v.ContentType},       // rsct
		"\n")

	signature, err := exported.ComputeUDCHMACSHA256(userDelegationCredential, stringToSign)
	if err != nil {
		return QueryParameters{}, err
	}

	p := QueryParameters{
		// Common SAS parameters
		version:         v.Version,
		protocol:        v.Protocol,
		startTime:       v.StartTime,
		expiryTime:      v.ExpiryTime,
		permissions:     v.Permissions,
		ipRange:         v.IPRange,
		encryptionScope: v.EncryptionScope,

		// Container/Blob-specific SAS parameters
		resource:             resource,
		identifier:           v.Identifier,
		cacheControl:         v.CacheControl,
		contentDisposition:   v.ContentDisposition,
		contentEncoding:      v.ContentEncoding,
		contentLanguage:      v.ContentLanguage,
		contentType:          v.ContentType,
		snapshotTime:         v.SnapshotTime,
		signedDirectoryDepth: getDirectoryDepth(v.Directory),
		authorizedObjectID:   v.AuthorizedObjectID,
		unauthorizedObjectID: v.UnauthorizedObjectID,
		correlationID:        v.CorrelationID,
		// Calculated SAS signature
		signature: signature,
	}

	//User delegation SAS specific parameters
	p.signedOID = *udk.SignedOID
	p.signedTID = *udk.SignedTID
	p.signedStart = *udk.SignedStart
	p.signedExpiry = *udk.SignedExpiry
	p.signedService = *udk.SignedService
	p.signedVersion = *udk.SignedVersion

	return p, nil
}