mirror of
				https://github.com/nabbar/golib.git
				synced 2025-10-31 11:06:23 +08:00 
			
		
		
		
	Package Archives:
- fix security arbitrary path - fix linter Package AWS: - implement resolver v2 Package Cobra: - fix linter Package Config/component: - fix linter Package Context/Config: - Add function to set context Package Database/KV...: - Fix error - Fix collision pointer - Fix models - Fix circular dependencies - Add function Delete on driver, table and item - Add function new on drvier to prevent collision data when create item on table get / walk Package Duration: - Add type Duration based on time.Duration to allow transform duration to string instead of int64 nanosecond - Add function to parse in json, yaml, toml, text, cbor - Add function to allow convert type into mapstructure (spf13 viper, cobra...) Package File/Perm: - Add type Perm based on os.FileMode to allow marshall / unmashall it into octal form instead of string representation (-rwxrwxrwx) - Add function to marshall / unmarshall in json, yaml, toml, text, cbor - Add function to allow convert type into mapstructure (spf13 viper, cobra...) Package File/progress: - Fix linter Package HTTPServer : - Fix linter - Fix security by adding a default value if not set on config Package ioutils: - Fix Linter Package LDAP: - Add Clone function Package logger/hookfile: - Fix linter Package nats: - Fix linter Package Network/Protocol: - Fix bug with quote / Dbl Quote on unmarshall Package Password: - Replace password with crypto rand instead of math rand Package Size: - Fix potential overflow - Add function to format value into Int32, Int, Uint32, Uint, Float32 - Add function to parse Float64 into type Size Package Socket: - change config uint32 to golib Size, time.Duration to golib Duration - add TLS managment to server TCP, discard for UDP & Unix file Local Domain - add function Info Server to print information of server when listen is starting
This commit is contained in:
		
							
								
								
									
										6
									
								
								.github/workflows/go.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/go.yml
									
									
									
									
										vendored
									
									
								
							| @@ -96,17 +96,17 @@ jobs: | |||||||
|         continue-on-error: false |         continue-on-error: false | ||||||
|         run: | |         run: | | ||||||
|           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') |           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') | ||||||
|           CGO_ENABLED=1 GOOS=linux GOARCH=amd64 GOAMD64=v4 go build -a -v -race -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) |           CGO_ENABLED=1 GOOS=linux GOARCH=amd64 GOAMD64=v4 go build -a -race -installsuffix cgo -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) | ||||||
|  |  | ||||||
|       - name: Test Build Windows/amd64 with CGO |       - name: Test Build Windows/amd64 with CGO | ||||||
|         continue-on-error: false |         continue-on-error: false | ||||||
|         run: | |         run: | | ||||||
|           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') |           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') | ||||||
|           CC=/usr/bin/x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOAMD64=v4 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) |           CC=/usr/bin/x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 GOAMD64=v4 go build -a -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) | ||||||
|  |  | ||||||
|       - name: Test Build Darwin/arm64 with suffix/CGO |       - name: Test Build Darwin/arm64 with suffix/CGO | ||||||
|         continue-on-error: false |         continue-on-error: false | ||||||
|         run: | |         run: | | ||||||
|           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') |           IGNORE_BUILD=$(sed '/^[[:space:]]*$/d' "build.$(go env | grep GOARCH | cut -d'=' -f2 | tr -d '"' | tr -d "'")" | tr '\n' '|') | ||||||
|           CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOAMD64=v1 go build -a -v -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) |           CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 GOAMD64=v1 go build -a -ldflags "-w -s -extldflags '-static' " $(go list ./... | grep -vPi ${IGNORE_BUILD::-1}) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -41,9 +41,10 @@ func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error { | |||||||
|  |  | ||||||
| 	r := bzip2.NewReader(src) | 	r := bzip2.NewReader(src) | ||||||
|  |  | ||||||
| 	//nolint #nosec | 	// #nosec | ||||||
| 	/* #nosec */ | 	_, e := io.Copy(dst, r) | ||||||
| 	if _, e := io.Copy(dst, r); e != nil { |  | ||||||
|  | 	if e != nil { | ||||||
| 		return ErrorIOCopy.Error(e) | 		return ErrorIOCopy.Error(e) | ||||||
| 	} else if _, e = dst.Seek(0, io.SeekStart); e != nil { | 	} else if _, e = dst.Seek(0, io.SeekStart); e != nil { | ||||||
| 		return ErrorFileSeek.Error(e) | 		return ErrorFileSeek.Error(e) | ||||||
|   | |||||||
| @@ -29,9 +29,8 @@ import ( | |||||||
| 	gz "compress/gzip" | 	gz "compress/gzip" | ||||||
| 	"io" | 	"io" | ||||||
|  |  | ||||||
| 	libfpg "github.com/nabbar/golib/file/progress" |  | ||||||
|  |  | ||||||
| 	"github.com/nabbar/golib/errors" | 	"github.com/nabbar/golib/errors" | ||||||
|  | 	libfpg "github.com/nabbar/golib/file/progress" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error { | func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error { | ||||||
| @@ -50,9 +49,10 @@ func GetFile(src io.ReadSeeker, dst io.WriteSeeker) errors.Error { | |||||||
| 		_ = r.Close() | 		_ = r.Close() | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	//nolint #nosec | 	// #nosec | ||||||
| 	/* #nosec */ | 	_, e = io.Copy(dst, r) | ||||||
| 	if _, e = io.Copy(dst, r); e != nil { |  | ||||||
|  | 	if e != nil { | ||||||
| 		return ErrorIOCopy.Error(e) | 		return ErrorIOCopy.Error(e) | ||||||
| 	} else if _, e = dst.Seek(0, io.SeekStart); e != nil { | 	} else if _, e = dst.Seek(0, io.SeekStart); e != nil { | ||||||
| 		return ErrorFileSeek.Error(e) | 		return ErrorFileSeek.Error(e) | ||||||
| @@ -88,6 +88,7 @@ func GetGunZipSize(src io.ReadSeeker) int64 { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var n int64 | 	var n int64 | ||||||
|  | 	// #nosec | ||||||
| 	n, e = io.Copy(io.Discard, r) | 	n, e = io.Copy(io.Discard, r) | ||||||
|  |  | ||||||
| 	if e != nil { | 	if e != nil { | ||||||
|   | |||||||
| @@ -33,10 +33,9 @@ import ( | |||||||
| 	"runtime" | 	"runtime" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	libfpg "github.com/nabbar/golib/file/progress" |  | ||||||
|  |  | ||||||
| 	libarc "github.com/nabbar/golib/archive/archive" | 	libarc "github.com/nabbar/golib/archive/archive" | ||||||
| 	liberr "github.com/nabbar/golib/errors" | 	liberr "github.com/nabbar/golib/errors" | ||||||
|  | 	libfpg "github.com/nabbar/golib/file/progress" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error { | func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error { | ||||||
| @@ -93,9 +92,11 @@ func GetAll(src io.ReadSeeker, outputFolder string, defaultDirPerm os.FileMode) | |||||||
| 			return ErrorTarNext.Error(e) | 			return ErrorTarNext.Error(e) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		dst := filepath.Join(outputFolder, libarc.CleanPath(strings.Replace(h.Name, ".."+string(filepath.Separator), "", -1))) | ||||||
|  |  | ||||||
| 		//nolint #nosec | 		//nolint #nosec | ||||||
| 		/* #nosec */ | 		/* #nosec */ | ||||||
| 		if err := writeContent(r, h, filepath.Join(outputFolder, libarc.CleanPath(h.Name)), defaultDirPerm); err != nil { | 		if err := writeContent(r, h, dst, defaultDirPerm); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -30,11 +30,11 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
| 	libfpg "github.com/nabbar/golib/file/progress" |  | ||||||
|  |  | ||||||
| 	arcmod "github.com/nabbar/golib/archive/archive" | 	arcmod "github.com/nabbar/golib/archive/archive" | ||||||
| 	liberr "github.com/nabbar/golib/errors" | 	liberr "github.com/nabbar/golib/errors" | ||||||
|  | 	libfpg "github.com/nabbar/golib/file/progress" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error { | func GetFile(src, dst libfpg.Progress, filenameContain, filenameRegex string) liberr.Error { | ||||||
| @@ -119,9 +119,10 @@ func GetAll(src libfpg.Progress, outputFolder string, defaultDirPerm os.FileMode | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//nolint #nosec | 		dst := filepath.Join(outputFolder, arcmod.CleanPath(strings.Replace(f.Name, ".."+string(filepath.Separator), "..", -1))) | ||||||
| 		/* #nosec */ |  | ||||||
| 		if err := writeContent(f, filepath.Join(outputFolder, arcmod.CleanPath(f.Name)), defaultDirPerm); err != nil { | 		// #nosec | ||||||
|  | 		if err := writeContent(f, dst, defaultDirPerm); err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -175,9 +176,10 @@ func writeContent(f *zip.File, out string, defaultDirPerm os.FileMode) (err libe | |||||||
| 		return ErrorZipFileOpen.Error(e) | 		return ErrorZipFileOpen.Error(e) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	//nolint #nosec | 	// #nosec | ||||||
| 	/* #nosec */ | 	_, e = io.Copy(dst, r) | ||||||
| 	if _, e = io.Copy(dst, r); e != nil { |  | ||||||
|  | 	if e != nil { | ||||||
| 		return ErrorIOCopy.Error(e) | 		return ErrorIOCopy.Error(e) | ||||||
| 	} else if e = dst.Close(); e != nil { | 	} else if e = dst.Close(); e != nil { | ||||||
| 		return ErrorFileClose.Error(e) | 		return ErrorFileClose.Error(e) | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ package bucket | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  |  | ||||||
|  | 	sdkaws "github.com/aws/aws-sdk-go-v2/aws" | ||||||
| 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" | 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" | ||||||
| 	sdkstp "github.com/aws/aws-sdk-go-v2/service/s3/types" | 	sdkstp "github.com/aws/aws-sdk-go-v2/service/s3/types" | ||||||
| 	libhlp "github.com/nabbar/golib/aws/helper" | 	libhlp "github.com/nabbar/golib/aws/helper" | ||||||
| @@ -64,10 +65,12 @@ func (cli *client) _create(RegionConstraint string, lockEnable bool) error { | |||||||
|  |  | ||||||
| 	if RegionConstraint != "" { | 	if RegionConstraint != "" { | ||||||
| 		in.CreateBucketConfiguration.LocationConstraint = sdkstp.BucketLocationConstraint(RegionConstraint) | 		in.CreateBucketConfiguration.LocationConstraint = sdkstp.BucketLocationConstraint(RegionConstraint) | ||||||
|  | 	} else { | ||||||
|  | 		in.CreateBucketConfiguration.LocationConstraint = sdkstp.BucketLocationConstraint(cli.GetRegion()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if lockEnable { | 	if lockEnable { | ||||||
| 		in.ObjectLockEnabledForBucket = true | 		in.ObjectLockEnabledForBucket = sdkaws.Bool(true) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	out, err := cli.s3.CreateBucket(cli.GetContext(), in) | 	out, err := cli.s3.CreateBucket(cli.GetContext(), in) | ||||||
|   | |||||||
| @@ -118,7 +118,9 @@ func (c *client) _NewClientIAM(ctx context.Context, httpClient *http.Client) (*s | |||||||
| 		EndpointOptions: sdkiam.EndpointResolverOptions{ | 		EndpointOptions: sdkiam.EndpointResolverOptions{ | ||||||
| 			DisableHTTPS: !c.c.IsHTTPs(), | 			DisableHTTPS: !c.c.IsHTTPs(), | ||||||
| 		}, | 		}, | ||||||
|  | 		BaseEndpoint:       sdkaws.String(c.c.GetEndpoint().String()), | ||||||
| 		EndpointResolver:   c._NewIAMResolver(cfg), | 		EndpointResolver:   c._NewIAMResolver(cfg), | ||||||
|  | 		EndpointResolverV2: c._NewIAMResolverV2(c.c), | ||||||
| 		HTTPSignerV4:       sig, | 		HTTPSignerV4:       sig, | ||||||
| 		Region:             cfg.Region, | 		Region:             cfg.Region, | ||||||
| 		Retryer:            ret, | 		Retryer:            ret, | ||||||
| @@ -161,7 +163,9 @@ func (c *client) _NewClientS3(ctx context.Context, httpClient *http.Client) (*sd | |||||||
| 		EndpointOptions: sdksss.EndpointResolverOptions{ | 		EndpointOptions: sdksss.EndpointResolverOptions{ | ||||||
| 			DisableHTTPS: !c.c.IsHTTPs(), | 			DisableHTTPS: !c.c.IsHTTPs(), | ||||||
| 		}, | 		}, | ||||||
|  | 		BaseEndpoint:       sdkaws.String(c.c.GetEndpoint().String()), | ||||||
| 		EndpointResolver:   c._NewS3Resolver(cfg), | 		EndpointResolver:   c._NewS3Resolver(cfg), | ||||||
|  | 		EndpointResolverV2: c._NewS3ResolverV2(c.c), | ||||||
| 		HTTPSignerV4:       sig, | 		HTTPSignerV4:       sig, | ||||||
| 		Region:             cfg.Region, | 		Region:             cfg.Region, | ||||||
| 		Retryer:            ret, | 		Retryer:            ret, | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ func (m *mpu) Copy(fromBucket, fromObject, fromVersionId string) error { | |||||||
| 			Bucket:          sdkaws.String(bck), | 			Bucket:          sdkaws.String(bck), | ||||||
| 			CopySource:      sdkaws.String(src), | 			CopySource:      sdkaws.String(src), | ||||||
| 			Key:             sdkaws.String(obj), | 			Key:             sdkaws.String(obj), | ||||||
| 			PartNumber:      m.Counter() + 1, | 			PartNumber:      sdkaws.Int32(m.Counter() + 1), | ||||||
| 			UploadId:        sdkaws.String(mid), | 			UploadId:        sdkaws.String(mid), | ||||||
| 			CopySourceRange: sdkaws.String("bytes=" + p), | 			CopySourceRange: sdkaws.String("bytes=" + p), | ||||||
| 			RequestPayer:    sdktyp.RequestPayerRequester, | 			RequestPayer:    sdktyp.RequestPayerRequester, | ||||||
| @@ -121,7 +121,9 @@ func (m *mpu) getCopyPart(fromBucket, fromObject, fromVersionId string) []string | |||||||
| 		return res | 		return res | ||||||
| 	} else if hdo == nil || hdo.ETag == nil || len(*hdo.ETag) < 1 { | 	} else if hdo == nil || hdo.ETag == nil || len(*hdo.ETag) < 1 { | ||||||
| 		return res | 		return res | ||||||
| 	} else if size := hdo.ContentLength; size < 1 { | 	} else if s := hdo.ContentLength; s == nil { | ||||||
|  | 		return res | ||||||
|  | 	} else if size := *s; size < 1 { | ||||||
| 		return res | 		return res | ||||||
| 	} else { | 	} else { | ||||||
| 		var i int64 = 0 | 		var i int64 = 0 | ||||||
|   | |||||||
| @@ -98,7 +98,7 @@ func (m *mpu) RegisterPart(etag string) { | |||||||
| 	m.n++ | 	m.n++ | ||||||
| 	m.l = append(m.l, sdktyp.CompletedPart{ | 	m.l = append(m.l, sdktyp.CompletedPart{ | ||||||
| 		ETag:       sdkaws.String(strings.Replace(etag, "\"", "", -1)), | 		ETag:       sdkaws.String(strings.Replace(etag, "\"", "", -1)), | ||||||
| 		PartNumber: m.n, | 		PartNumber: sdkaws.Int32(m.n), | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -154,8 +154,8 @@ func (m *mpu) AddPart(r io.Reader) (n int64, e error) { | |||||||
| 		Bucket:        sdkaws.String(bck), | 		Bucket:        sdkaws.String(bck), | ||||||
| 		Key:           sdkaws.String(obj), | 		Key:           sdkaws.String(obj), | ||||||
| 		UploadId:      sdkaws.String(mid), | 		UploadId:      sdkaws.String(mid), | ||||||
| 		PartNumber:    m.Counter() + 1, | 		PartNumber:    sdkaws.Int32(m.Counter() + 1), | ||||||
| 		ContentLength: n, | 		ContentLength: sdkaws.Int64(n), | ||||||
| 		Body:          tmp, | 		Body:          tmp, | ||||||
| 		RequestPayer:  sdktyp.RequestPayerRequester, | 		RequestPayer:  sdktyp.RequestPayerRequester, | ||||||
| 		ContentMD5:    sdkaws.String(hss), | 		ContentMD5:    sdkaws.String(hss), | ||||||
|   | |||||||
| @@ -75,7 +75,7 @@ func (cli *client) SetRetention(object, version string, bypass bool, until time. | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if bypass { | 	if bypass { | ||||||
| 		in.BypassGovernanceRetention = true | 		in.BypassGovernanceRetention = sdkaws.Bool(true) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	switch { | 	switch { | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ import ( | |||||||
| func (cli *client) MultipartList(keyMarker, markerId string) (uploads []sdktyp.MultipartUpload, nextKeyMarker string, nextIdMarker string, count int64, e error) { | func (cli *client) MultipartList(keyMarker, markerId string) (uploads []sdktyp.MultipartUpload, nextKeyMarker string, nextIdMarker string, count int64, e error) { | ||||||
| 	in := &sdksss.ListMultipartUploadsInput{ | 	in := &sdksss.ListMultipartUploadsInput{ | ||||||
| 		Bucket:     sdkaws.String(cli.GetBucketName()), | 		Bucket:     sdkaws.String(cli.GetBucketName()), | ||||||
| 		MaxUploads: 1000, | 		MaxUploads: sdkaws.Int32(1000), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if keyMarker != "" && markerId != "" { | 	if keyMarker != "" && markerId != "" { | ||||||
| @@ -54,10 +54,17 @@ func (cli *client) MultipartList(keyMarker, markerId string) (uploads []sdktyp.M | |||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, "", "", 0, cli.GetError(err) | 		return nil, "", "", 0, cli.GetError(err) | ||||||
| 	} else if out.IsTruncated { | 	} | ||||||
| 		return out.Uploads, *out.NextKeyMarker, *out.NextUploadIdMarker, int64(out.MaxUploads), nil |  | ||||||
|  | 	var maxKeys int32 | ||||||
|  | 	if out != nil && out.MaxUploads != nil { | ||||||
|  | 		maxKeys = *out.MaxUploads | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if out != nil && out.IsTruncated != nil && *out.IsTruncated { | ||||||
|  | 		return out.Uploads, *out.NextKeyMarker, *out.NextUploadIdMarker, int64(maxKeys), nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return out.Uploads, "", "", int64(out.MaxUploads), nil | 		return out.Uploads, "", "", int64(maxKeys), nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,9 +30,8 @@ import ( | |||||||
| 	"mime" | 	"mime" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  |  | ||||||
| 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" |  | ||||||
|  |  | ||||||
| 	sdkaws "github.com/aws/aws-sdk-go-v2/aws" | 	sdkaws "github.com/aws/aws-sdk-go-v2/aws" | ||||||
|  | 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" | ||||||
| 	sdktps "github.com/aws/aws-sdk-go-v2/service/s3/types" | 	sdktps "github.com/aws/aws-sdk-go-v2/service/s3/types" | ||||||
| 	libhlp "github.com/nabbar/golib/aws/helper" | 	libhlp "github.com/nabbar/golib/aws/helper" | ||||||
| ) | ) | ||||||
| @@ -58,10 +57,17 @@ func (cli *client) ListPrefix(continuationToken string, prefix string) ([]sdktps | |||||||
|  |  | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, "", 0, cli.GetError(err) | 		return nil, "", 0, cli.GetError(err) | ||||||
| 	} else if out.IsTruncated { | 	} | ||||||
| 		return out.Contents, *out.NextContinuationToken, int64(out.KeyCount), nil |  | ||||||
|  | 	var maxKeys int32 | ||||||
|  | 	if out != nil && out.MaxKeys != nil { | ||||||
|  | 		maxKeys = *out.MaxKeys | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if out != nil && out.IsTruncated != nil && *out.IsTruncated { | ||||||
|  | 		return out.Contents, *out.NextContinuationToken, int64(maxKeys), nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return out.Contents, "", int64(out.KeyCount), nil | 		return out.Contents, "", int64(maxKeys), nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -104,7 +110,7 @@ func (cli *client) WalkPrefix(prefix string, f WalkFunc) error { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if out.IsTruncated { | 		if out != nil && out.IsTruncated != nil && *out.IsTruncated { | ||||||
| 			t = out.NextContinuationToken | 			t = out.NextContinuationToken | ||||||
| 		} else { | 		} else { | ||||||
| 			return e | 			return e | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ import ( | |||||||
| func (cli *client) VersionList(prefix, keyMarker, markerId string) (version []sdktps.ObjectVersion, delMarker []sdktps.DeleteMarkerEntry, nextKeyMarker, nextMarkerId string, count int64, err error) { | func (cli *client) VersionList(prefix, keyMarker, markerId string) (version []sdktps.ObjectVersion, delMarker []sdktps.DeleteMarkerEntry, nextKeyMarker, nextMarkerId string, count int64, err error) { | ||||||
| 	in := sdksss.ListObjectVersionsInput{ | 	in := sdksss.ListObjectVersionsInput{ | ||||||
| 		Bucket:  cli.GetBucketAws(), | 		Bucket:  cli.GetBucketAws(), | ||||||
| 		MaxKeys: 1000, | 		MaxKeys: sdkaws.Int32(1000), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if prefix != "" { | 	if prefix != "" { | ||||||
| @@ -54,10 +54,17 @@ func (cli *client) VersionList(prefix, keyMarker, markerId string) (version []sd | |||||||
|  |  | ||||||
| 	if e != nil { | 	if e != nil { | ||||||
| 		return nil, nil, "", "", 0, cli.GetError(e) | 		return nil, nil, "", "", 0, cli.GetError(e) | ||||||
| 	} else if out.IsTruncated { | 	} | ||||||
| 		return out.Versions, out.DeleteMarkers, *out.NextKeyMarker, *out.NextVersionIdMarker, int64(out.MaxKeys), nil |  | ||||||
|  | 	var maxKeys int32 | ||||||
|  | 	if out != nil && out.MaxKeys != nil { | ||||||
|  | 		maxKeys = *out.MaxKeys | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if out != nil && out.IsTruncated != nil && *out.IsTruncated { | ||||||
|  | 		return out.Versions, out.DeleteMarkers, *out.NextKeyMarker, *out.NextVersionIdMarker, int64(maxKeys), nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return out.Versions, out.DeleteMarkers, "", "", int64(out.MaxKeys), nil | 		return out.Versions, out.DeleteMarkers, "", "", int64(maxKeys), nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -68,7 +75,7 @@ func (cli *client) VersionWalk(fv VersionWalkFunc, fd DelMakWalkFunc) error { | |||||||
| func (cli *client) VersionWalkPrefix(prefix string, fv VersionWalkFunc, fd DelMakWalkFunc) error { | func (cli *client) VersionWalkPrefix(prefix string, fv VersionWalkFunc, fd DelMakWalkFunc) error { | ||||||
| 	in := sdksss.ListObjectVersionsInput{ | 	in := sdksss.ListObjectVersionsInput{ | ||||||
| 		Bucket:  cli.GetBucketAws(), | 		Bucket:  cli.GetBucketAws(), | ||||||
| 		MaxKeys: 1000, | 		MaxKeys: sdkaws.Int32(1000), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if prefix != "" { | 	if prefix != "" { | ||||||
| @@ -117,7 +124,7 @@ func (cli *client) VersionWalkPrefix(prefix string, fv VersionWalkFunc, fd DelMa | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if out.IsTruncated { | 		if out != nil && out.IsTruncated != nil && *out.IsTruncated { | ||||||
| 			km = out.NextKeyMarker | 			km = out.NextKeyMarker | ||||||
| 			mi = out.NextVersionIdMarker | 			mi = out.NextVersionIdMarker | ||||||
| 		} else { | 		} else { | ||||||
| @@ -181,8 +188,10 @@ func (cli *client) VersionSize(object, version string) (size int64, err error) { | |||||||
|  |  | ||||||
| 	if h, err = cli.VersionHead(object, version); err != nil { | 	if h, err = cli.VersionHead(object, version); err != nil { | ||||||
| 		return | 		return | ||||||
|  | 	} else if h != nil && h.ContentLength != nil { | ||||||
|  | 		return *h.ContentLength, nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return h.ContentLength, nil | 		return 0, nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -207,7 +216,7 @@ func (cli *client) VersionDeleteLock(check bool, object, version string, byPassG | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if byPassGovernance { | 	if byPassGovernance { | ||||||
| 		in.BypassGovernanceRetention = true | 		in.BypassGovernanceRetention = sdkaws.Bool(true) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	_, err := cli.s3.DeleteObject(cli.GetContext(), &in) | 	_, err := cli.s3.DeleteObject(cli.GetContext(), &in) | ||||||
|   | |||||||
| @@ -26,9 +26,13 @@ | |||||||
| package aws | package aws | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"net/url" | ||||||
|  |  | ||||||
| 	sdkaws "github.com/aws/aws-sdk-go-v2/aws" | 	sdkaws "github.com/aws/aws-sdk-go-v2/aws" | ||||||
| 	sdkiam "github.com/aws/aws-sdk-go-v2/service/iam" | 	sdkiam "github.com/aws/aws-sdk-go-v2/service/iam" | ||||||
| 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" | 	sdksss "github.com/aws/aws-sdk-go-v2/service/s3" | ||||||
|  | 	awsedp "github.com/aws/smithy-go/endpoints" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type resolverIam struct { | type resolverIam struct { | ||||||
| @@ -39,6 +43,14 @@ func (r *resolverIam) ResolveEndpoint(region string, options sdkiam.EndpointReso | |||||||
| 	return r.r("iam", region) | 	return r.r("iam", region) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type resolverIamV2 struct { | ||||||
|  | 	r func(service, region string) (awsedp.Endpoint, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *resolverIamV2) ResolveEndpoint(ctx context.Context, params sdkiam.EndpointParameters) (awsedp.Endpoint, error) { | ||||||
|  | 	return r.r("iam", *params.Region) | ||||||
|  | } | ||||||
|  |  | ||||||
| type resolverS3 struct { | type resolverS3 struct { | ||||||
| 	r func(service, region string) (sdkaws.Endpoint, error) | 	r func(service, region string) (sdkaws.Endpoint, error) | ||||||
| } | } | ||||||
| @@ -47,14 +59,62 @@ func (r *resolverS3) ResolveEndpoint(region string, options sdksss.EndpointResol | |||||||
| 	return r.r("s3", region) | 	return r.r("s3", region) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type resolverS3V2 struct { | ||||||
|  | 	r func(service, region string) (awsedp.Endpoint, error) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *resolverS3V2) ResolveEndpoint(ctx context.Context, params sdksss.EndpointParameters) (awsedp.Endpoint, error) { | ||||||
|  | 	return r.r("s3", *params.Region) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *client) _NewIAMResolver(cfg *sdkaws.Config) sdkiam.EndpointResolver { | func (c *client) _NewIAMResolver(cfg *sdkaws.Config) sdkiam.EndpointResolver { | ||||||
| 	return &resolverIam{ | 	return &resolverIam{ | ||||||
| 		r: cfg.EndpointResolver.ResolveEndpoint, | 		r: cfg.EndpointResolver.ResolveEndpoint, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *client) _NewIAMResolverV2(cfg Config) sdkiam.EndpointResolverV2 { | ||||||
|  | 	return &resolverIamV2{ | ||||||
|  | 		r: func(service, region string) (awsedp.Endpoint, error) { | ||||||
|  | 			edp, err := cfg.ResolveEndpoint(service, region) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return awsedp.Endpoint{}, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			uri, err := url.Parse(edp.URL) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return awsedp.Endpoint{}, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return awsedp.Endpoint{ | ||||||
|  | 				URI: *uri, | ||||||
|  | 			}, nil | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *client) _NewS3Resolver(cfg *sdkaws.Config) sdksss.EndpointResolver { | func (c *client) _NewS3Resolver(cfg *sdkaws.Config) sdksss.EndpointResolver { | ||||||
| 	return &resolverS3{ | 	return &resolverS3{ | ||||||
| 		r: cfg.EndpointResolver.ResolveEndpoint, | 		r: cfg.EndpointResolver.ResolveEndpoint, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *client) _NewS3ResolverV2(cfg Config) sdksss.EndpointResolverV2 { | ||||||
|  | 	return &resolverS3V2{ | ||||||
|  | 		r: func(service, region string) (awsedp.Endpoint, error) { | ||||||
|  | 			edp, err := cfg.ResolveEndpoint(service, region) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return awsedp.Endpoint{}, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			uri, err := url.Parse(edp.URL) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return awsedp.Endpoint{}, err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			return awsedp.Endpoint{ | ||||||
|  | 				URI: *uri, | ||||||
|  | 			}, nil | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -61,7 +61,9 @@ func (c *cobra) AddCommandCompletion() { | |||||||
| 				os.Exit(1) | 				os.Exit(1) | ||||||
| 			} else if len(args) >= 2 { | 			} else if len(args) >= 2 { | ||||||
| 				file = filepath.Clean(args[1]) | 				file = filepath.Clean(args[1]) | ||||||
| 				c.getLog().CheckError(loglvl.ErrorLevel, loglvl.NilLevel, "create file path", os.MkdirAll(filepath.Dir(file), 0755)) | 				// #nosec | ||||||
|  | 				e := os.MkdirAll(filepath.Dir(file), 0755) | ||||||
|  | 				c.getLog().CheckError(loglvl.ErrorLevel, loglvl.NilLevel, "create file path", e) | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			switch strings.ToLower(args[0]) { | 			switch strings.ToLower(args[0]) { | ||||||
|   | |||||||
| @@ -110,6 +110,7 @@ func (c *cobra) ConfigureWriteConfig(basename string, defaultConfig func() io.Re | |||||||
| 		cfgFile = strings.TrimRight(cfgFile, ext) + ".json" | 		cfgFile = strings.TrimRight(cfgFile, ext) + ".json" | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// #nosec | ||||||
| 	fs, err = os.OpenFile(cfgFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) | 	fs, err = os.OpenFile(cfgFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
|   | |||||||
| @@ -147,6 +147,7 @@ func (o *componentSmtp) _GetTLS() libtls.TLSConfig { | |||||||
|  |  | ||||||
| func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config { | func (o *componentSmtp) _GetTLSConfig(cfg libtls.Config) *tls.Config { | ||||||
| 	if i, e := cfg.NewFrom(o._GetTLS()); e != nil { | 	if i, e := cfg.NewFrom(o._GetTLS()); e != nil { | ||||||
|  | 		// #nosec | ||||||
| 		return &tls.Config{} | 		return &tls.Config{} | ||||||
| 	} else { | 	} else { | ||||||
| 		return i.TlsConfig("") | 		return i.TlsConfig("") | ||||||
|   | |||||||
| @@ -52,6 +52,7 @@ type Config[T comparable] interface { | |||||||
| 	MapManage[T] | 	MapManage[T] | ||||||
| 	Context | 	Context | ||||||
|  |  | ||||||
|  | 	SetContext(ctx FuncContext) | ||||||
| 	Clone(ctx context.Context) Config[T] | 	Clone(ctx context.Context) Config[T] | ||||||
| 	Merge(cfg Config[T]) bool | 	Merge(cfg Config[T]) bool | ||||||
| 	Walk(fct FuncWalk[T]) bool | 	Walk(fct FuncWalk[T]) bool | ||||||
| @@ -81,6 +82,18 @@ type configContext[T comparable] struct { | |||||||
| 	x FuncContext | 	x FuncContext | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *configContext[T]) SetContext(ctx FuncContext) { | ||||||
|  | 	c.n.Lock() | ||||||
|  | 	defer c.n.Unlock() | ||||||
|  |  | ||||||
|  | 	if ctx == nil { | ||||||
|  | 		ctx = context.Background | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	c.Context = ctx() | ||||||
|  | 	c.x = ctx | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *configContext[T]) Delete(key T) { | func (c *configContext[T]) Delete(key T) { | ||||||
| 	if c.Err() != nil { | 	if c.Err() != nil { | ||||||
| 		c.Clean() | 		c.Clean() | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ const ( | |||||||
| 	ErrorBadInstance | 	ErrorBadInstance | ||||||
| 	ErrorGetFunction | 	ErrorGetFunction | ||||||
| 	ErrorSetFunction | 	ErrorSetFunction | ||||||
|  | 	ErrorDelFunction | ||||||
| 	ErrorListFunction | 	ErrorListFunction | ||||||
| 	ErrorFunctionParams | 	ErrorFunctionParams | ||||||
| ) | ) | ||||||
| @@ -62,6 +63,8 @@ func getMessage(code liberr.CodeError) (message string) { | |||||||
| 		return "missing get function of " + pkgName | 		return "missing get function of " + pkgName | ||||||
| 	case ErrorSetFunction: | 	case ErrorSetFunction: | ||||||
| 		return "missing set function of " + pkgName | 		return "missing set function of " + pkgName | ||||||
|  | 	case ErrorDelFunction: | ||||||
|  | 		return "missing del function of " + pkgName | ||||||
| 	case ErrorListFunction: | 	case ErrorListFunction: | ||||||
| 		return "missing list function of " + pkgName | 		return "missing list function of " + pkgName | ||||||
| 	case ErrorFunctionParams: | 	case ErrorFunctionParams: | ||||||
|   | |||||||
| @@ -26,25 +26,33 @@ | |||||||
|  |  | ||||||
| package kvdriver | package kvdriver | ||||||
|  |  | ||||||
| type FctWalk[K comparable, M any] func(key K, model M) bool | import ( | ||||||
|  | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| type KVDriver[K comparable, M any] interface { | ) | ||||||
| 	Get(key K, model *M) error |  | ||||||
| 	Set(key K, model M) error |  | ||||||
| 	List() ([]K, error) |  | ||||||
| 	Walk(fct FctWalk[K, M]) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | type FuncNew[K comparable, M any] func() libkvt.KVDriver[K, M] | ||||||
| type FuncGet[K comparable, M any] func(key K) (M, error) | type FuncGet[K comparable, M any] func(key K) (M, error) | ||||||
| type FuncSet[K comparable, M any] func(key K, model M) error | type FuncSet[K comparable, M any] func(key K, model M) error | ||||||
|  | type FuncDel[K comparable] func(key K) error | ||||||
| type FuncList[K comparable, M any] func() ([]K, error) | type FuncList[K comparable, M any] func() ([]K, error) | ||||||
| type FuncWalk[K comparable, M any] func(fct FctWalk[K, M]) error | type FuncWalk[K comparable, M any] func(fct libkvt.FctWalk[K, M]) error | ||||||
|  |  | ||||||
| type Driver[K comparable, M any] struct { |  | ||||||
| 	KVDriver[K, M] |  | ||||||
|  |  | ||||||
|  | type drv[K comparable, M any] struct { | ||||||
|  | 	FctNew  FuncNew[K, M] | ||||||
| 	FctGet  FuncGet[K, M] | 	FctGet  FuncGet[K, M] | ||||||
| 	FctSet  FuncSet[K, M] | 	FctSet  FuncSet[K, M] | ||||||
|  | 	FctDel  FuncDel[K] | ||||||
| 	FctList FuncList[K, M] | 	FctList FuncList[K, M] | ||||||
| 	FctWalk FuncWalk[K, M] // optional | 	FctWalk FuncWalk[K, M] // optional | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func New[K comparable, M any](fn FuncNew[K, M], fg FuncGet[K, M], fs FuncSet[K, M], fd FuncDel[K], fl FuncList[K, M], fw FuncWalk[K, M]) libkvt.KVDriver[K, M] { | ||||||
|  | 	return &drv[K, M]{ | ||||||
|  | 		FctNew:  fn, | ||||||
|  | 		FctGet:  fg, | ||||||
|  | 		FctSet:  fs, | ||||||
|  | 		FctDel:  fd, | ||||||
|  | 		FctList: fl, | ||||||
|  | 		FctWalk: fw, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -26,7 +26,26 @@ | |||||||
|  |  | ||||||
| package kvdriver | package kvdriver | ||||||
|  |  | ||||||
| func (o *Driver[K, M]) Get(key K, model *M) error { | import ( | ||||||
|  | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (o *drv[K, M]) New() libkvt.KVDriver[K, M] { | ||||||
|  | 	if o.FctNew != nil { | ||||||
|  | 		return o.FctNew() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return &drv[K, M]{ | ||||||
|  | 		FctNew:  o.FctNew, | ||||||
|  | 		FctGet:  o.FctGet, | ||||||
|  | 		FctSet:  o.FctSet, | ||||||
|  | 		FctDel:  o.FctDel, | ||||||
|  | 		FctList: o.FctList, | ||||||
|  | 		FctWalk: o.FctWalk, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *drv[K, M]) Get(key K, model *M) error { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return ErrorBadInstance.Error(nil) | 		return ErrorBadInstance.Error(nil) | ||||||
| 	} else if o.FctGet == nil { | 	} else if o.FctGet == nil { | ||||||
| @@ -38,7 +57,7 @@ func (o *Driver[K, M]) Get(key K, model *M) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, M]) Set(key K, model M) error { | func (o *drv[K, M]) Set(key K, model M) error { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return ErrorBadInstance.Error(nil) | 		return ErrorBadInstance.Error(nil) | ||||||
| 	} else if o.FctSet == nil { | 	} else if o.FctSet == nil { | ||||||
| @@ -48,7 +67,17 @@ func (o *Driver[K, M]) Set(key K, model M) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, M]) List() ([]K, error) { | func (o *drv[K, M]) Del(key K) error { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return ErrorBadInstance.Error(nil) | ||||||
|  | 	} else if o.FctDel == nil { | ||||||
|  | 		return ErrorSetFunction.Error(nil) | ||||||
|  | 	} else { | ||||||
|  | 		return o.FctDel(key) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *drv[K, M]) List() ([]K, error) { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil, ErrorBadInstance.Error(nil) | 		return nil, ErrorBadInstance.Error(nil) | ||||||
| 	} else if o.FctList == nil { | 	} else if o.FctList == nil { | ||||||
| @@ -58,7 +87,7 @@ func (o *Driver[K, M]) List() ([]K, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, M]) Walk(fct FctWalk[K, M]) error { | func (o *drv[K, M]) Walk(fct libkvt.FctWalk[K, M]) error { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return ErrorBadInstance.Error(nil) | 		return ErrorBadInstance.Error(nil) | ||||||
| 	} else if fct == nil { | 	} else if fct == nil { | ||||||
| @@ -70,7 +99,7 @@ func (o *Driver[K, M]) Walk(fct FctWalk[K, M]) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, M]) fakeWalk(fct FctWalk[K, M]) error { | func (o *drv[K, M]) fakeWalk(fct libkvt.FctWalk[K, M]) error { | ||||||
| 	if l, e := o.List(); e != nil { | 	if l, e := o.List(); e != nil { | ||||||
| 		return e | 		return e | ||||||
| 	} else { | 	} else { | ||||||
|   | |||||||
| @@ -38,6 +38,7 @@ const ( | |||||||
| 	ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgDatabaseKVItm | 	ErrorParamEmpty liberr.CodeError = iota + liberr.MinPkgDatabaseKVItm | ||||||
| 	ErrorLoadFunction | 	ErrorLoadFunction | ||||||
| 	ErrorStoreFunction | 	ErrorStoreFunction | ||||||
|  | 	ErrorRemoveFunction | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| @@ -57,6 +58,8 @@ func getMessage(code liberr.CodeError) (message string) { | |||||||
| 		return "missing load function of " + pkgName | 		return "missing load function of " + pkgName | ||||||
| 	case ErrorStoreFunction: | 	case ErrorStoreFunction: | ||||||
| 		return "missing store function of " + pkgName | 		return "missing store function of " + pkgName | ||||||
|  | 	case ErrorRemoveFunction: | ||||||
|  | 		return "missing remove function of " + pkgName | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return liberr.NullMessage | 	return liberr.NullMessage | ||||||
|   | |||||||
| @@ -26,40 +26,21 @@ | |||||||
|  |  | ||||||
| package kvitem | package kvitem | ||||||
|  |  | ||||||
| import "sync/atomic" | import ( | ||||||
|  | 	"sync/atomic" | ||||||
|  |  | ||||||
| type FuncLoad[K comparable, M any] func(key K, model *M) error | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| type FuncStore[K comparable, M any] func(key K, model M) error | ) | ||||||
|  |  | ||||||
| type KVItem[K comparable, M any] interface { |  | ||||||
| 	Set(model M) |  | ||||||
| 	Get() M |  | ||||||
|  |  | ||||||
| 	Load() error |  | ||||||
| 	Store(force bool) error |  | ||||||
| 	Clean() |  | ||||||
|  |  | ||||||
| 	HasChange() bool |  | ||||||
|  |  | ||||||
| 	RegisterFctLoad(fct FuncLoad[K, M]) |  | ||||||
| 	RegisterFctStore(fct FuncStore[K, M]) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func New[K comparable, M any](key K) KVItem[K, M] { |  | ||||||
| 	var ( |  | ||||||
| 		ml = new(atomic.Value) |  | ||||||
| 		mw = new(atomic.Value) |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	ml.Store(nil) |  | ||||||
| 	mw.Store(nil) |  | ||||||
|  |  | ||||||
|  | func New[K comparable, M any](drv libkvt.KVDriver[K, M], key K) libkvt.KVItem[K, M] { | ||||||
| 	return &itm[K, M]{ | 	return &itm[K, M]{ | ||||||
| 		k:  key, | 		k:  key, | ||||||
| 		ml: ml, | 		d:  drv, | ||||||
| 		ms: mw, | 		ml: new(atomic.Value), | ||||||
| 		fl: nil, | 		ms: new(atomic.Value), | ||||||
| 		fs: nil, | 		fl: new(atomic.Value), | ||||||
|  | 		fs: new(atomic.Value), | ||||||
|  | 		fr: new(atomic.Value), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,9 +29,12 @@ package kvitem | |||||||
| import ( | import ( | ||||||
| 	"reflect" | 	"reflect" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
|  |  | ||||||
|  | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type itm[K comparable, M any] struct { | type itm[K comparable, M any] struct { | ||||||
|  | 	d libkvt.KVDriver[K, M] | ||||||
| 	k K // key | 	k K // key | ||||||
|  |  | ||||||
| 	ml *atomic.Value // model read | 	ml *atomic.Value // model read | ||||||
| @@ -39,165 +42,145 @@ type itm[K comparable, M any] struct { | |||||||
|  |  | ||||||
| 	fl *atomic.Value | 	fl *atomic.Value | ||||||
| 	fs *atomic.Value | 	fs *atomic.Value | ||||||
|  | 	fr *atomic.Value | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) RegisterFctLoad(fct FuncLoad[K, M]) { | func (o *itm[K, M]) getDriver() libkvt.KVDriver[K, M] { | ||||||
| 	o.fl.Store(fct) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (o *itm[K, M]) getFctLoad() FuncLoad[K, M] { |  | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	i := o.fs.Load() | 	return o.d | ||||||
| 	if i == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} else if f, k := i.(FuncLoad[K, M]); !k { |  | ||||||
| 		return nil |  | ||||||
| 	} else { |  | ||||||
| 		return f |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (o *itm[K, M]) RegisterFctStore(fct FuncStore[K, M]) { |  | ||||||
| 	o.fs.Store(fct) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (o *itm[K, M]) getFctStore() FuncStore[K, M] { |  | ||||||
| 	if o == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	i := o.fs.Load() |  | ||||||
| 	if i == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} else if f, k := i.(FuncStore[K, M]); !k { |  | ||||||
| 		return nil |  | ||||||
| 	} else { |  | ||||||
| 		return f |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) Set(model M) { | func (o *itm[K, M]) Set(model M) { | ||||||
| 	if o == nil { | 	var val = reflect.ValueOf(model) | ||||||
| 		return | 	o.ms.Store(val.Interface()) | ||||||
| 	} | } | ||||||
|  |  | ||||||
| 	m := o.ml.Load() | func (o *itm[K, M]) setModelLoad(mod M) { | ||||||
|  | 	var val = reflect.ValueOf(mod) | ||||||
|  | 	o.ml.Store(val.Interface()) | ||||||
|  | } | ||||||
|  |  | ||||||
| 	// model not loaded, so store new model | func (o *itm[K, M]) getModelLoad() M { | ||||||
| 	if m == nil { | 	var mod M | ||||||
| 		o.ms.Store(model) | 	if i := o.ml.Load(); i == nil { | ||||||
| 		// model loaded and new model given not same, so store new model | 		return mod | ||||||
| 	} else if !reflect.DeepEqual(m.(M), model) { | 	} else if v, k := i.(M); !k { | ||||||
| 		o.ms.Store(model) | 		return mod | ||||||
| 		// model loaded and given model are same, so don't store new model |  | ||||||
| 	} else { | 	} else { | ||||||
| 		o.ms.Store(nil) | 		return v | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *itm[K, M]) getModelStore() M { | ||||||
|  | 	var mod M | ||||||
|  | 	if i := o.ms.Load(); i == nil { | ||||||
|  | 		return mod | ||||||
|  | 	} else if v, k := i.(M); !k { | ||||||
|  | 		return mod | ||||||
|  | 	} else { | ||||||
|  | 		return v | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *itm[K, M]) Key() K { | ||||||
|  | 	if o == nil { | ||||||
|  | 		var k K | ||||||
|  | 		return k | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return o.k | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) Get() M { | func (o *itm[K, M]) Get() M { | ||||||
|  | 	var ( | ||||||
|  | 		tmp M | ||||||
|  | 		mod M | ||||||
|  | 	) | ||||||
|  |  | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return *(new(M)) | 		return mod | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// update exist so latest fresh value | 	mod = o.getModelStore() | ||||||
| 	m := o.ms.Load() |  | ||||||
| 	if m != nil { |  | ||||||
| 		if v, k := m.(M); k { |  | ||||||
| 			return v |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// load model exist so return last model load | 	if reflect.DeepEqual(mod, tmp) { | ||||||
| 	m = o.ml.Load() | 		mod = o.getModelLoad() | ||||||
| 	if m != nil { |  | ||||||
| 		if v, k := m.(M); k { |  | ||||||
| 			return v |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// nothing load, so return new instance | 	// nothing load, so return new instance | ||||||
| 	return *(new(M)) | 	return mod | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) Load() error { | func (o *itm[K, M]) Load() error { | ||||||
| 	var fct FuncLoad[K, M] | 	var ( | ||||||
|  | 		mod M | ||||||
|  | 		drv = o.getDriver() | ||||||
|  | 	) | ||||||
|  |  | ||||||
| 	if fct = o.getFctLoad(); fct == nil { | 	if drv == nil { | ||||||
| 		return ErrorLoadFunction.Error(nil) | 		return ErrorLoadFunction.Error(nil) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	m := *(new(M)) | 	if e := drv.Get(o.k, &mod); e == nil { | ||||||
| 	e := fct(o.k, &m) | 		o.setModelLoad(mod) | ||||||
|  | 	} else { | ||||||
| 	if e == nil { | 		return e | ||||||
| 		o.ml.Store(m) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return e | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) Store(force bool) error { | func (o *itm[K, M]) Store(force bool) error { | ||||||
| 	var fct FuncStore[K, M] | 	var drv = o.getDriver() | ||||||
|  |  | ||||||
| 	if fct = o.getFctStore(); fct == nil { | 	if drv == nil { | ||||||
| 		return ErrorStoreFunction.Error(nil) | 		return ErrorStoreFunction.Error(nil) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	m := o.ms.Load() | 	var ( | ||||||
| 	if m != nil { | 		lod M | ||||||
| 		return fct(o.k, m.(M)) | 		str M | ||||||
| 	} else if !force { | 	) | ||||||
|  |  | ||||||
|  | 	_ = o.Load() | ||||||
|  |  | ||||||
|  | 	str = o.getModelStore() | ||||||
|  | 	if reflect.DeepEqual(lod, str) { | ||||||
|  | 		str = o.getModelLoad() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	lod = o.getModelLoad() | ||||||
|  | 	if !reflect.DeepEqual(lod, str) { | ||||||
|  | 		return drv.Set(o.k, str) | ||||||
|  | 	} else if force { | ||||||
|  | 		return drv.Set(o.k, lod) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *itm[K, M]) Remove() error { | ||||||
|  | 	drv := o.getDriver() | ||||||
|  |  | ||||||
|  | 	if drv == nil { | ||||||
|  | 		return ErrorStoreFunction.Error(nil) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// no update, but force store, so use load model | 	return drv.Del(o.k) | ||||||
| 	m = o.ml.Load() |  | ||||||
| 	if m != nil { |  | ||||||
| 		return fct(o.k, m.(M)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	// no update and no load, but force store, so use new instance of model |  | ||||||
| 	m = *(new(M)) |  | ||||||
| 	return fct(o.k, m.(M)) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) Clean() { | func (o *itm[K, M]) Clean() { | ||||||
| 	o.ml.Store(nil) | 	var tmp M | ||||||
| 	o.ms.Store(nil) | 	o.setModelLoad(tmp) | ||||||
|  | 	o.Set(tmp) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *itm[K, M]) HasChange() bool { | func (o *itm[K, M]) HasChange() bool { | ||||||
| 	r := o.ml.Load() | 	r := o.getModelLoad() | ||||||
| 	w := o.ms.Load() | 	w := o.getModelStore() | ||||||
|  |  | ||||||
| 	if r == nil && w == nil { | 	return !reflect.DeepEqual(r, w) | ||||||
| 		// not loaded and not store, so no change |  | ||||||
| 		return false |  | ||||||
| 	} else if r == nil { |  | ||||||
| 		// not loaded but store is set, so has been updated |  | ||||||
| 		return true |  | ||||||
| 	} else if w == nil { |  | ||||||
| 		// loaded and not store, so no change |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	mr, kr := r.(M) |  | ||||||
| 	mw, kw := w.(M) |  | ||||||
|  |  | ||||||
| 	if !kr && !kw { |  | ||||||
| 		// no valid model, so no change |  | ||||||
| 		return false |  | ||||||
| 	} else if !kr { |  | ||||||
| 		// not valid model for load, but valid for store, so has been updated |  | ||||||
| 		return true |  | ||||||
| 	} else if !kw { |  | ||||||
| 		// valid model for load, but not valid for store, so like no change |  | ||||||
| 		return false |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return !reflect.DeepEqual(mr, mw) |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ const ( | |||||||
| 	ErrorBadInstance | 	ErrorBadInstance | ||||||
| 	ErrorGetFunction | 	ErrorGetFunction | ||||||
| 	ErrorSetFunction | 	ErrorSetFunction | ||||||
|  | 	ErrorDelFunction | ||||||
| 	ErrorListFunction | 	ErrorListFunction | ||||||
| 	ErrorFunctionParams | 	ErrorFunctionParams | ||||||
| ) | ) | ||||||
| @@ -62,6 +63,8 @@ func getMessage(code liberr.CodeError) (message string) { | |||||||
| 		return "missing get function of " + pkgName | 		return "missing get function of " + pkgName | ||||||
| 	case ErrorSetFunction: | 	case ErrorSetFunction: | ||||||
| 		return "missing set function of " + pkgName | 		return "missing set function of " + pkgName | ||||||
|  | 	case ErrorDelFunction: | ||||||
|  | 		return "missing del function of " + pkgName | ||||||
| 	case ErrorListFunction: | 	case ErrorListFunction: | ||||||
| 		return "missing list function of " + pkgName | 		return "missing list function of " + pkgName | ||||||
| 	case ErrorFunctionParams: | 	case ErrorFunctionParams: | ||||||
|   | |||||||
| @@ -27,17 +27,29 @@ | |||||||
| package kvmap | package kvmap | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	libkvd "github.com/nabbar/golib/database/kvdriver" | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | type FuncNew[K comparable, M any] func() libkvt.KVDriver[K, M] | ||||||
| type FuncGet[K comparable, MK comparable] func(key K) (map[MK]any, error) | type FuncGet[K comparable, MK comparable] func(key K) (map[MK]any, error) | ||||||
| type FuncSet[K comparable, MK comparable] func(key K, model map[MK]any) error | type FuncSet[K comparable, MK comparable] func(key K, model map[MK]any) error | ||||||
|  | type FuncDel[K comparable] func(key K) error | ||||||
| type FuncList[K comparable, MK comparable] func() ([]K, error) | type FuncList[K comparable, MK comparable] func() ([]K, error) | ||||||
|  |  | ||||||
| type Driver[K comparable, MK comparable, M any] struct { | type drv[K comparable, MK comparable, M any] struct { | ||||||
| 	libkvd.KVDriver[K, M] | 	FctNew  FuncNew[K, M] | ||||||
|  |  | ||||||
| 	FctGet  FuncGet[K, MK] | 	FctGet  FuncGet[K, MK] | ||||||
| 	FctSet  FuncSet[K, MK] | 	FctSet  FuncSet[K, MK] | ||||||
|  | 	FctDel  FuncDel[K] | ||||||
| 	FctList FuncList[K, MK] | 	FctList FuncList[K, MK] | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func New[K comparable, MK comparable, M any](fn FuncNew[K, M], fg FuncGet[K, MK], fs FuncSet[K, MK], fd FuncDel[K], fl FuncList[K, MK]) libkvt.KVDriver[K, M] { | ||||||
|  | 	return &drv[K, MK, M]{ | ||||||
|  | 		FctNew:  fn, | ||||||
|  | 		FctGet:  fg, | ||||||
|  | 		FctSet:  fs, | ||||||
|  | 		FctDel:  fd, | ||||||
|  | 		FctList: fl, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -29,10 +29,10 @@ package kvmap | |||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
|  |  | ||||||
| 	libkvd "github.com/nabbar/golib/database/kvdriver" | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error { | func (o *drv[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error { | ||||||
| 	if p, e := json.Marshal(model); e != nil { | 	if p, e := json.Marshal(model); e != nil { | ||||||
| 		return e | 		return e | ||||||
| 	} else { | 	} else { | ||||||
| @@ -40,7 +40,7 @@ func (o *Driver[K, MK, M]) serialize(model *M, modelMap *map[MK]any) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error { | func (o *drv[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error { | ||||||
| 	if p, e := json.Marshal(modelMap); e != nil { | 	if p, e := json.Marshal(modelMap); e != nil { | ||||||
| 		return e | 		return e | ||||||
| 	} else { | 	} else { | ||||||
| @@ -48,7 +48,16 @@ func (o *Driver[K, MK, M]) unSerialize(modelMap *map[MK]any, model *M) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) Get(key K, model *M) error { | func (o *drv[K, MK, M]) New() libkvt.KVDriver[K, M] { | ||||||
|  | 	return &drv[K, MK, M]{ | ||||||
|  | 		FctGet:  o.FctGet, | ||||||
|  | 		FctSet:  o.FctSet, | ||||||
|  | 		FctDel:  o.FctDel, | ||||||
|  | 		FctList: o.FctList, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *drv[K, MK, M]) Get(key K, model *M) error { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return ErrorBadInstance.Error(nil) | 		return ErrorBadInstance.Error(nil) | ||||||
| 	} else if o.FctGet == nil { | 	} else if o.FctGet == nil { | ||||||
| @@ -60,7 +69,7 @@ func (o *Driver[K, MK, M]) Get(key K, model *M) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) Set(key K, model M) error { | func (o *drv[K, MK, M]) Set(key K, model M) error { | ||||||
| 	var m = make(map[MK]any) | 	var m = make(map[MK]any) | ||||||
|  |  | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| @@ -74,7 +83,17 @@ func (o *Driver[K, MK, M]) Set(key K, model M) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) List() ([]K, error) { | func (o *drv[K, MK, M]) Del(key K) error { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return ErrorBadInstance.Error(nil) | ||||||
|  | 	} else if o.FctDel == nil { | ||||||
|  | 		return ErrorDelFunction.Error(nil) | ||||||
|  | 	} else { | ||||||
|  | 		return o.FctDel(key) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *drv[K, MK, M]) List() ([]K, error) { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil, ErrorBadInstance.Error(nil) | 		return nil, ErrorBadInstance.Error(nil) | ||||||
| 	} else if o.FctList == nil { | 	} else if o.FctList == nil { | ||||||
| @@ -84,7 +103,7 @@ func (o *Driver[K, MK, M]) List() ([]K, error) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *Driver[K, MK, M]) Walk(fct libkvd.FctWalk[K, M]) error { | func (o *drv[K, MK, M]) Walk(fct libkvt.FctWalk[K, M]) error { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return ErrorBadInstance.Error(nil) | 		return ErrorBadInstance.Error(nil) | ||||||
| 	} else if fct == nil { | 	} else if fct == nil { | ||||||
|   | |||||||
| @@ -27,25 +27,11 @@ | |||||||
| package kvtable | package kvtable | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"sync/atomic" | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
|  |  | ||||||
| 	libkvd "github.com/nabbar/golib/database/kvdriver" |  | ||||||
| 	libkvi "github.com/nabbar/golib/database/kvitem" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type FuncWalk[K comparable, M any] func(kv libkvi.KVItem[K, M]) bool | func New[K comparable, M any](drv libkvt.KVDriver[K, M]) libkvt.KVTable[K, M] { | ||||||
|  |  | ||||||
| type KVTable[K comparable, M any] interface { |  | ||||||
| 	Get(key K) (libkvi.KVItem[K, M], error) |  | ||||||
| 	List() ([]libkvi.KVItem[K, M], error) |  | ||||||
| 	Walk(fct FuncWalk[K, M]) error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func New[K comparable, M any](drv libkvd.KVDriver[K, M]) KVTable[K, M] { |  | ||||||
| 	d := new(atomic.Value) |  | ||||||
| 	d.Store(drv) |  | ||||||
|  |  | ||||||
| 	return &tbl[K, M]{ | 	return &tbl[K, M]{ | ||||||
| 		d: d, | 		d: drv, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -27,66 +27,58 @@ | |||||||
| package kvtable | package kvtable | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"sync/atomic" |  | ||||||
|  |  | ||||||
| 	libkvd "github.com/nabbar/golib/database/kvdriver" |  | ||||||
| 	libkvs "github.com/nabbar/golib/database/kvitem" | 	libkvs "github.com/nabbar/golib/database/kvitem" | ||||||
|  | 	libkvt "github.com/nabbar/golib/database/kvtypes" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type tbl[K comparable, M any] struct { | type tbl[K comparable, M any] struct { | ||||||
| 	d *atomic.Value | 	d libkvt.KVDriver[K, M] | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *tbl[K, M]) getDriver() libkvd.KVDriver[K, M] { | func (o *tbl[K, M]) getDriver() libkvt.KVDriver[K, M] { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	i := o.d.Load() | 	if o.d == nil { | ||||||
| 	if i == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} else if d, k := i.(libkvd.KVDriver[K, M]); !k { |  | ||||||
| 		return nil | 		return nil | ||||||
| 	} else { | 	} else { | ||||||
| 		return d | 		return o.d | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *tbl[K, M]) Get(key K) (libkvs.KVItem[K, M], error) { | func (o *tbl[K, M]) Get(key K) (libkvt.KVItem[K, M], error) { | ||||||
| 	var kvs = libkvs.New[K, M](key) |  | ||||||
|  |  | ||||||
| 	if drv := o.getDriver(); drv == nil { | 	if drv := o.getDriver(); drv == nil { | ||||||
| 		return nil, ErrorBadDriver.Error(nil) | 		return nil, ErrorBadDriver.Error(nil) | ||||||
| 	} else { | 	} else { | ||||||
| 		kvs.RegisterFctLoad(drv.Get) | 		var kvi = libkvs.New[K, M](drv.New(), key) | ||||||
| 		kvs.RegisterFctStore(drv.Set) | 		e := kvi.Load() | ||||||
|  | 		return kvi, e | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return kvs, kvs.Load() |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *tbl[K, M]) Walk(fct FuncWalk[K, M]) error { | func (o *tbl[K, M]) Del(key K) error { | ||||||
|  | 	if drv := o.getDriver(); drv == nil { | ||||||
|  | 		return ErrorBadDriver.Error(nil) | ||||||
|  | 	} else { | ||||||
|  | 		return drv.Del(key) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *tbl[K, M]) Walk(fct libkvt.FuncWalk[K, M]) error { | ||||||
| 	if drv := o.getDriver(); drv == nil { | 	if drv := o.getDriver(); drv == nil { | ||||||
| 		return ErrorBadDriver.Error(nil) | 		return ErrorBadDriver.Error(nil) | ||||||
| 	} else { | 	} else { | ||||||
| 		return drv.Walk(func(key K, model M) bool { | 		return drv.Walk(func(key K, model M) bool { | ||||||
| 			var kvs = libkvs.New[K, M](key) | 			kvi := libkvs.New[K, M](drv.New(), key) | ||||||
|  | 			kvi.Set(model) | ||||||
| 			kvs.RegisterFctStore(drv.Set) | 			return fct(kvi) | ||||||
| 			kvs.RegisterFctLoad(func(k K, m *M) error { |  | ||||||
| 				*m = model |  | ||||||
| 				return nil |  | ||||||
| 			}) |  | ||||||
| 			_ = kvs.Load() |  | ||||||
| 			kvs.RegisterFctLoad(drv.Get) |  | ||||||
|  |  | ||||||
| 			return fct(kvs) |  | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *tbl[K, M]) List() ([]libkvs.KVItem[K, M], error) { | func (o *tbl[K, M]) List() ([]libkvt.KVItem[K, M], error) { | ||||||
| 	var res = make([]libkvs.KVItem[K, M], 0) | 	var res = make([]libkvt.KVItem[K, M], 0) | ||||||
|  |  | ||||||
| 	if drv := o.getDriver(); drv == nil { | 	if drv := o.getDriver(); drv == nil { | ||||||
| 		return nil, ErrorBadDriver.Error(nil) | 		return nil, ErrorBadDriver.Error(nil) | ||||||
| @@ -94,12 +86,7 @@ func (o *tbl[K, M]) List() ([]libkvs.KVItem[K, M], error) { | |||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		for _, k := range l { | 		for _, k := range l { | ||||||
| 			var kvs = libkvs.New[K, M](k) | 			res = append(res, libkvs.New[K, M](drv.New(), k)) | ||||||
|  |  | ||||||
| 			kvs.RegisterFctLoad(drv.Get) |  | ||||||
| 			kvs.RegisterFctStore(drv.Set) |  | ||||||
|  |  | ||||||
| 			res = append(res, kvs) |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return res, nil | 		return res, nil | ||||||
|   | |||||||
							
								
								
									
										38
									
								
								database/kvtypes/driver.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								database/kvtypes/driver.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | /* | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2023 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package kvtypes | ||||||
|  |  | ||||||
|  | type FctWalk[K comparable, M any] func(key K, model M) bool | ||||||
|  |  | ||||||
|  | type KVDriver[K comparable, M any] interface { | ||||||
|  | 	New() KVDriver[K, M] | ||||||
|  | 	Get(key K, model *M) error | ||||||
|  | 	Set(key K, model M) error | ||||||
|  | 	Del(key K) error | ||||||
|  | 	List() ([]K, error) | ||||||
|  | 	Walk(fct FctWalk[K, M]) error | ||||||
|  | } | ||||||
							
								
								
									
										40
									
								
								database/kvtypes/item.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								database/kvtypes/item.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | /* | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2023 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package kvtypes | ||||||
|  |  | ||||||
|  | type KVItem[K comparable, M any] interface { | ||||||
|  | 	Set(model M) | ||||||
|  | 	Get() M | ||||||
|  | 	Key() K | ||||||
|  |  | ||||||
|  | 	Load() error | ||||||
|  | 	Store(force bool) error | ||||||
|  | 	Remove() error | ||||||
|  | 	Clean() | ||||||
|  |  | ||||||
|  | 	HasChange() bool | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								database/kvtypes/table.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								database/kvtypes/table.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | /* | ||||||
|  |  * MIT License | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2023 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  * of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  * in the Software without restriction, including without limitation the rights | ||||||
|  |  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  * copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  * furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  * The above copyright notice and this permission notice shall be included in all | ||||||
|  |  * copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  * SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package kvtypes | ||||||
|  |  | ||||||
|  | type FuncWalk[K comparable, M any] func(kv KVItem[K, M]) bool | ||||||
|  |  | ||||||
|  | type KVTable[K comparable, M any] interface { | ||||||
|  | 	Get(key K) (KVItem[K, M], error) | ||||||
|  | 	Del(key K) error | ||||||
|  | 	List() ([]KVItem[K, M], error) | ||||||
|  | 	Walk(fct FuncWalk[K, M]) error | ||||||
|  | } | ||||||
							
								
								
									
										87
									
								
								duration/encode.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								duration/encode.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package duration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	"gopkg.in/yaml.v3" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (d Duration) MarshalJSON() ([]byte, error) { | ||||||
|  | 	t := d.String() | ||||||
|  | 	b := make([]byte, 0, len(t)+2) | ||||||
|  | 	b = append(b, '"') | ||||||
|  | 	b = append(b, []byte(t)...) | ||||||
|  | 	b = append(b, '"') | ||||||
|  | 	return b, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) UnmarshalJSON(bytes []byte) error { | ||||||
|  | 	return d.unmarshall(bytes) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) MarshalYAML() (interface{}, error) { | ||||||
|  | 	return d.MarshalJSON() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) UnmarshalYAML(value *yaml.Node) error { | ||||||
|  | 	return d.unmarshall([]byte(value.Value)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) MarshalTOML() ([]byte, error) { | ||||||
|  | 	return d.MarshalJSON() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) UnmarshalTOML(i interface{}) error { | ||||||
|  | 	if b, k := i.([]byte); k { | ||||||
|  | 		return d.unmarshall(b) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if b, k := i.(string); k { | ||||||
|  | 		return d.parseString(b) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return fmt.Errorf("size: value not in valid format") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) MarshalText() ([]byte, error) { | ||||||
|  | 	return []byte(d.String()), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) UnmarshalText(bytes []byte) error { | ||||||
|  | 	return d.unmarshall(bytes) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) MarshalCBOR() ([]byte, error) { | ||||||
|  | 	return []byte(d.String()), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) UnmarshalCBOR(bytes []byte) error { | ||||||
|  | 	return d.unmarshall(bytes) | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								duration/format.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								duration/format.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package duration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"math" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (d Duration) Time() time.Duration { | ||||||
|  | 	return time.Duration(d) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) String() string { | ||||||
|  | 	return time.Duration(d).String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d Duration) Days() int64 { | ||||||
|  | 	t := math.Floor(d.Time().Hours()) | ||||||
|  |  | ||||||
|  | 	if t > math.MaxInt64 { | ||||||
|  | 		return math.MaxInt64 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int64(t) | ||||||
|  | } | ||||||
							
								
								
									
										62
									
								
								duration/interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								duration/interface.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package duration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Duration time.Duration | ||||||
|  |  | ||||||
|  | func Parse(s string) (Duration, error) { | ||||||
|  | 	return parseString(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ParseByte(p []byte) (Duration, error) { | ||||||
|  | 	return parseString(string(p)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Seconds(i int64) Duration { | ||||||
|  | 	return Duration(time.Duration(i) * time.Second) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Minutes(i int64) Duration { | ||||||
|  | 	return Duration(time.Duration(i) * time.Minute) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Hours(i int64) Duration { | ||||||
|  | 	return Duration(time.Duration(i) * time.Hour) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Days(i int64) Duration { | ||||||
|  | 	return Duration(time.Duration(i) * time.Hour * 24) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ParseDuration(d time.Duration) Duration { | ||||||
|  | 	return Duration(d) | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								duration/model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								duration/model.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package duration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  |  | ||||||
|  | 	libmap "github.com/mitchellh/mapstructure" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func ViperDecoderHook() libmap.DecodeHookFuncType { | ||||||
|  | 	return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { | ||||||
|  | 		var ( | ||||||
|  | 			z = Duration(0) | ||||||
|  | 			t string | ||||||
|  | 			k bool | ||||||
|  | 		) | ||||||
|  |  | ||||||
|  | 		// Check if the data type matches the expected one | ||||||
|  | 		if from.Kind() != reflect.String { | ||||||
|  | 			return data, nil | ||||||
|  | 		} else if t, k = data.(string); !k { | ||||||
|  | 			return data, nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Check if the target type matches the expected one | ||||||
|  | 		if to != reflect.TypeOf(z) { | ||||||
|  | 			return data, nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Format/decode/parse the data and return the new value | ||||||
|  | 		return parseString(t) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								duration/parse.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								duration/parse.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package duration | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func parseString(s string) (Duration, error) { | ||||||
|  | 	s = strings.Replace(s, "\"", "", -1) | ||||||
|  | 	s = strings.Replace(s, "'", "", -1) | ||||||
|  | 	if v, e := time.ParseDuration(s); e != nil { | ||||||
|  | 		return 0, e | ||||||
|  | 	} else { | ||||||
|  | 		return Duration(v), nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) parseString(s string) error { | ||||||
|  | 	if v, e := parseString(s); e != nil { | ||||||
|  | 		return e | ||||||
|  | 	} else { | ||||||
|  | 		*d = v | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (d *Duration) unmarshall(val []byte) error { | ||||||
|  | 	if tmp, err := ParseByte(val); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else { | ||||||
|  | 		*d = tmp | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										87
									
								
								file/perm/encode.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								file/perm/encode.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package perm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  |  | ||||||
|  | 	"gopkg.in/yaml.v3" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (p Perm) MarshalJSON() ([]byte, error) { | ||||||
|  | 	t := p.String() | ||||||
|  | 	b := make([]byte, 0, len(t)+2) | ||||||
|  | 	b = append(b, '"') | ||||||
|  | 	b = append(b, []byte(t)...) | ||||||
|  | 	b = append(b, '"') | ||||||
|  | 	return b, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) UnmarshalJSON(bytes []byte) error { | ||||||
|  | 	return p.unmarshall(bytes) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) MarshalYAML() (interface{}, error) { | ||||||
|  | 	return p.MarshalJSON() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) UnmarshalYAML(value *yaml.Node) error { | ||||||
|  | 	return p.unmarshall([]byte(value.Value)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) MarshalTOML() ([]byte, error) { | ||||||
|  | 	return p.MarshalJSON() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) UnmarshalTOML(i interface{}) error { | ||||||
|  | 	if b, k := i.([]byte); k { | ||||||
|  | 		return p.unmarshall(b) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if b, k := i.(string); k { | ||||||
|  | 		return p.parseString(b) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return fmt.Errorf("size: value not in valid format") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) MarshalText() ([]byte, error) { | ||||||
|  | 	return []byte(p.String()), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) UnmarshalText(bytes []byte) error { | ||||||
|  | 	return p.unmarshall(bytes) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) MarshalCBOR() ([]byte, error) { | ||||||
|  | 	return []byte(p.String()), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) UnmarshalCBOR(bytes []byte) error { | ||||||
|  | 	return p.unmarshall(bytes) | ||||||
|  | } | ||||||
							
								
								
									
										91
									
								
								file/perm/format.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								file/perm/format.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package perm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"math" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func (p Perm) FileMode() os.FileMode { | ||||||
|  | 	return os.FileMode(p.Uint64()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) String() string { | ||||||
|  | 	return fmt.Sprintf("%#o", p.Uint64()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Int64() int64 { | ||||||
|  | 	if uint64(p) > math.MaxInt64 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxInt64 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int64(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Int32() int32 { | ||||||
|  | 	if uint64(p) > math.MaxInt32 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxInt32 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int32(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Int() int { | ||||||
|  | 	if uint64(p) > math.MaxInt { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxInt | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Uint64() uint64 { | ||||||
|  | 	return uint64(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Uint32() uint32 { | ||||||
|  | 	if uint64(p) > math.MaxUint32 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxUint32 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return uint32(p) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p Perm) Uint() uint { | ||||||
|  | 	if uint64(p) > math.MaxUint { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxUint | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return uint(p) | ||||||
|  | } | ||||||
							
								
								
									
										51
									
								
								file/perm/interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								file/perm/interface.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package perm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"os" | ||||||
|  | 	"strconv" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type Perm os.FileMode | ||||||
|  |  | ||||||
|  | func Parse(s string) (Perm, error) { | ||||||
|  | 	return parseString(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ParseInt(i int) (Perm, error) { | ||||||
|  | 	return parseString(strconv.FormatInt(int64(i), 8)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ParseInt64(i int64) (Perm, error) { | ||||||
|  | 	return parseString(strconv.FormatInt(i, 8)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ParseByte(p []byte) (Perm, error) { | ||||||
|  | 	return parseString(string(p)) | ||||||
|  | } | ||||||
							
								
								
									
										59
									
								
								file/perm/model.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								file/perm/model.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package perm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"reflect" | ||||||
|  |  | ||||||
|  | 	libmap "github.com/mitchellh/mapstructure" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func ViperDecoderHook() libmap.DecodeHookFuncType { | ||||||
|  | 	return func(from reflect.Type, to reflect.Type, data interface{}) (interface{}, error) { | ||||||
|  | 		var ( | ||||||
|  | 			z = Perm(0) | ||||||
|  | 			t string | ||||||
|  | 			k bool | ||||||
|  | 		) | ||||||
|  |  | ||||||
|  | 		// Check if the data type matches the expected one | ||||||
|  | 		if from.Kind() != reflect.String { | ||||||
|  | 			return data, nil | ||||||
|  | 		} else if t, k = data.(string); !k { | ||||||
|  | 			return data, nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Check if the target type matches the expected one | ||||||
|  | 		if to != reflect.TypeOf(z) { | ||||||
|  | 			return data, nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Format/decode/parse the data and return the new value | ||||||
|  | 		return parseString(t) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										66
									
								
								file/perm/parse.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								file/perm/parse.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | /*********************************************************************************************************************** | ||||||
|  |  * | ||||||
|  |  *   MIT License | ||||||
|  |  * | ||||||
|  |  *   Copyright (c) 2022 Nicolas JUHEL | ||||||
|  |  * | ||||||
|  |  *   Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |  *   of this software and associated documentation files (the "Software"), to deal | ||||||
|  |  *   in the Software without restriction, including without limitation the rights | ||||||
|  |  *   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |  *   copies of the Software, and to permit persons to whom the Software is | ||||||
|  |  *   furnished to do so, subject to the following conditions: | ||||||
|  |  * | ||||||
|  |  *   The above copyright notice and this permission notice shall be included in all | ||||||
|  |  *   copies or substantial portions of the Software. | ||||||
|  |  * | ||||||
|  |  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |  *   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |  *   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |  *   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |  *   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |  *   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |  *   SOFTWARE. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  **********************************************************************************************************************/ | ||||||
|  |  | ||||||
|  | package perm | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"math" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func parseString(s string) (Perm, error) { | ||||||
|  | 	s = strings.Replace(s, "\"", "", -1) | ||||||
|  | 	s = strings.Replace(s, "'", "", -1) | ||||||
|  |  | ||||||
|  | 	if v, e := strconv.ParseUint(s, 8, 32); e != nil { | ||||||
|  | 		return 0, e | ||||||
|  | 	} else if v > math.MaxUint32 { | ||||||
|  | 		return Perm(0), fmt.Errorf("invalid permission") | ||||||
|  | 	} else { | ||||||
|  | 		return Perm(v), nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) parseString(s string) error { | ||||||
|  | 	if v, e := parseString(s); e != nil { | ||||||
|  | 		return e | ||||||
|  | 	} else { | ||||||
|  | 		*p = v | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (p *Perm) unmarshall(val []byte) error { | ||||||
|  | 	if tmp, err := ParseByte(val); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} else { | ||||||
|  | 		*p = tmp | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -85,7 +85,10 @@ type Progress interface { | |||||||
| } | } | ||||||
|  |  | ||||||
| func New(name string, flags int, perm os.FileMode) (Progress, error) { | func New(name string, flags int, perm os.FileMode) (Progress, error) { | ||||||
| 	if f, e := os.OpenFile(name, flags, perm); e != nil { | 	// #nosec | ||||||
|  | 	f, e := os.OpenFile(name, flags, perm) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		return &progress{ | 		return &progress{ | ||||||
| @@ -99,7 +102,10 @@ func New(name string, flags int, perm os.FileMode) (Progress, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Unique(basePath, pattern string) (Progress, error) { | func Unique(basePath, pattern string) (Progress, error) { | ||||||
| 	if f, e := os.CreateTemp(basePath, pattern); e != nil { | 	// #nosec | ||||||
|  | 	f, e := os.CreateTemp(basePath, pattern) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		return &progress{ | 		return &progress{ | ||||||
| @@ -113,7 +119,10 @@ func Unique(basePath, pattern string) (Progress, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Temp(pattern string) (Progress, error) { | func Temp(pattern string) (Progress, error) { | ||||||
| 	if f, e := os.CreateTemp("", pattern); e != nil { | 	// #nosec | ||||||
|  | 	f, e := os.CreateTemp("", pattern) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		return &progress{ | 		return &progress{ | ||||||
| @@ -127,7 +136,10 @@ func Temp(pattern string) (Progress, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Open(name string) (Progress, error) { | func Open(name string) (Progress, error) { | ||||||
| 	if f, e := os.Open(name); e != nil { | 	// #nosec | ||||||
|  | 	f, e := os.Open(name) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		return &progress{ | 		return &progress{ | ||||||
| @@ -141,7 +153,10 @@ func Open(name string) (Progress, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func Create(name string) (Progress, error) { | func Create(name string) (Progress, error) { | ||||||
| 	if f, e := os.Create(name); e != nil { | 	// #nosec | ||||||
|  | 	f, e := os.Create(name) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else { | 	} else { | ||||||
| 		return &progress{ | 		return &progress{ | ||||||
|   | |||||||
							
								
								
									
										132
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										132
									
								
								go.mod
									
									
									
									
									
								
							| @@ -2,25 +2,26 @@ module github.com/nabbar/golib | |||||||
|  |  | ||||||
| go 1.21 | go 1.21 | ||||||
|  |  | ||||||
| toolchain go1.21.1 | toolchain go1.21.3 | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	github.com/aws/aws-sdk-go-v2 v1.21.2 | 	github.com/aws/aws-sdk-go-v2 v1.23.1 | ||||||
| 	github.com/aws/aws-sdk-go-v2/config v1.18.45 | 	github.com/aws/aws-sdk-go-v2/config v1.25.4 | ||||||
| 	github.com/aws/aws-sdk-go-v2/credentials v1.13.43 | 	github.com/aws/aws-sdk-go-v2/credentials v1.16.3 | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/iam v1.22.7 | 	github.com/aws/aws-sdk-go-v2/service/iam v1.27.3 | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/s3 v1.40.2 | 	github.com/aws/aws-sdk-go-v2/service/s3 v1.43.1 | ||||||
| 	github.com/bits-and-blooms/bitset v1.10.0 | 	github.com/aws/smithy-go v1.17.0 | ||||||
|  | 	github.com/bits-and-blooms/bitset v1.11.0 | ||||||
| 	github.com/c-bata/go-prompt v0.2.6 | 	github.com/c-bata/go-prompt v0.2.6 | ||||||
| 	github.com/fatih/color v1.15.0 | 	github.com/fatih/color v1.16.0 | ||||||
| 	github.com/fsnotify/fsnotify v1.6.0 | 	github.com/fsnotify/fsnotify v1.7.0 | ||||||
| 	github.com/fxamacker/cbor/v2 v2.5.0 | 	github.com/fxamacker/cbor/v2 v2.5.0 | ||||||
| 	github.com/gin-gonic/gin v1.9.1 | 	github.com/gin-gonic/gin v1.9.1 | ||||||
| 	github.com/go-ldap/ldap/v3 v3.4.6 | 	github.com/go-ldap/ldap/v3 v3.4.6 | ||||||
| 	github.com/go-playground/validator/v10 v10.15.5 | 	github.com/go-playground/validator/v10 v10.16.0 | ||||||
| 	github.com/google/go-github/v33 v33.0.0 | 	github.com/google/go-github/v33 v33.0.0 | ||||||
| 	github.com/hashicorp/go-hclog v1.5.0 | 	github.com/hashicorp/go-hclog v1.5.0 | ||||||
| 	github.com/hashicorp/go-retryablehttp v0.7.4 | 	github.com/hashicorp/go-retryablehttp v0.7.5 | ||||||
| 	github.com/hashicorp/go-uuid v1.0.3 | 	github.com/hashicorp/go-uuid v1.0.3 | ||||||
| 	github.com/hashicorp/go-version v1.6.0 | 	github.com/hashicorp/go-version v1.6.0 | ||||||
| 	github.com/jlaffaye/ftp v0.2.0 | 	github.com/jlaffaye/ftp v0.2.0 | ||||||
| @@ -29,34 +30,34 @@ require ( | |||||||
| 	github.com/mattn/go-colorable v0.1.13 | 	github.com/mattn/go-colorable v0.1.13 | ||||||
| 	github.com/mitchellh/go-homedir v1.1.0 | 	github.com/mitchellh/go-homedir v1.1.0 | ||||||
| 	github.com/mitchellh/mapstructure v1.5.0 | 	github.com/mitchellh/mapstructure v1.5.0 | ||||||
| 	github.com/nats-io/jwt/v2 v2.5.2 | 	github.com/nats-io/jwt/v2 v2.5.3 | ||||||
| 	github.com/nats-io/nats-server/v2 v2.10.3 | 	github.com/nats-io/nats-server/v2 v2.10.5 | ||||||
| 	github.com/nats-io/nats.go v1.30.2 | 	github.com/nats-io/nats.go v1.31.0 | ||||||
| 	github.com/nutsdb/nutsdb v0.14.1 | 	github.com/nutsdb/nutsdb v0.14.3 | ||||||
| 	github.com/onsi/ginkgo/v2 v2.13.0 | 	github.com/onsi/ginkgo/v2 v2.13.1 | ||||||
| 	github.com/onsi/gomega v1.28.0 | 	github.com/onsi/gomega v1.30.0 | ||||||
| 	github.com/pelletier/go-toml v1.9.5 | 	github.com/pelletier/go-toml v1.9.5 | ||||||
| 	github.com/prometheus/client_golang v1.17.0 | 	github.com/prometheus/client_golang v1.17.0 | ||||||
| 	github.com/shirou/gopsutil v3.21.11+incompatible | 	github.com/shirou/gopsutil v3.21.11+incompatible | ||||||
| 	github.com/sirupsen/logrus v1.9.3 | 	github.com/sirupsen/logrus v1.9.3 | ||||||
| 	github.com/spf13/cobra v1.7.0 | 	github.com/spf13/cobra v1.8.0 | ||||||
| 	github.com/spf13/jwalterweatherman v1.1.0 | 	github.com/spf13/jwalterweatherman v1.1.0 | ||||||
| 	github.com/spf13/viper v1.17.0 | 	github.com/spf13/viper v1.17.0 | ||||||
| 	github.com/ugorji/go/codec v1.2.11 | 	github.com/ugorji/go/codec v1.2.11 | ||||||
| 	github.com/vbauerster/mpb/v8 v8.6.2 | 	github.com/vbauerster/mpb/v8 v8.6.2 | ||||||
| 	github.com/xanzy/go-gitlab v0.93.1 | 	github.com/xanzy/go-gitlab v0.94.0 | ||||||
| 	github.com/xhit/go-simple-mail v2.2.2+incompatible | 	github.com/xhit/go-simple-mail v2.2.2+incompatible | ||||||
| 	github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235 | 	github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235 | ||||||
| 	golang.org/x/exp v0.0.0-20231006140011-7918f672742d | 	golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa | ||||||
| 	golang.org/x/net v0.17.0 | 	golang.org/x/net v0.18.0 | ||||||
| 	golang.org/x/oauth2 v0.13.0 | 	golang.org/x/oauth2 v0.14.0 | ||||||
| 	golang.org/x/sync v0.4.0 | 	golang.org/x/sync v0.5.0 | ||||||
| 	golang.org/x/sys v0.13.0 | 	golang.org/x/sys v0.14.0 | ||||||
| 	golang.org/x/term v0.13.0 | 	golang.org/x/term v0.14.0 | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 | 	gopkg.in/yaml.v3 v3.0.1 | ||||||
| 	gorm.io/driver/clickhouse v0.5.1 | 	gorm.io/driver/clickhouse v0.5.1 | ||||||
| 	gorm.io/driver/mysql v1.5.2 | 	gorm.io/driver/mysql v1.5.2 | ||||||
| 	gorm.io/driver/postgres v1.5.3 | 	gorm.io/driver/postgres v1.5.4 | ||||||
| 	gorm.io/driver/sqlite v1.5.4 | 	gorm.io/driver/sqlite v1.5.4 | ||||||
| 	gorm.io/driver/sqlserver v1.5.2 | 	gorm.io/driver/sqlserver v1.5.2 | ||||||
| 	gorm.io/gorm v1.25.5 | 	gorm.io/gorm v1.25.5 | ||||||
| @@ -65,7 +66,7 @@ require ( | |||||||
| require ( | require ( | ||||||
| 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect | 	github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect | ||||||
| 	github.com/ClickHouse/ch-go v0.58.2 // indirect | 	github.com/ClickHouse/ch-go v0.58.2 // indirect | ||||||
| 	github.com/ClickHouse/clickhouse-go/v2 v2.14.3 // indirect | 	github.com/ClickHouse/clickhouse-go/v2 v2.15.0 // indirect | ||||||
| 	github.com/Masterminds/goutils v1.1.1 // indirect | 	github.com/Masterminds/goutils v1.1.1 // indirect | ||||||
| 	github.com/Masterminds/semver v1.5.0 // indirect | 	github.com/Masterminds/semver v1.5.0 // indirect | ||||||
| 	github.com/Masterminds/sprig v2.22.0+incompatible // indirect | 	github.com/Masterminds/sprig v2.22.0+incompatible // indirect | ||||||
| @@ -78,38 +79,36 @@ require ( | |||||||
| 	github.com/antlabs/stl v0.0.1 // indirect | 	github.com/antlabs/stl v0.0.1 // indirect | ||||||
| 	github.com/antlabs/timer v0.0.11 // indirect | 	github.com/antlabs/timer v0.0.11 // indirect | ||||||
| 	github.com/armon/go-metrics v0.4.1 // indirect | 	github.com/armon/go-metrics v0.4.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 // indirect | 	github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13 // indirect | 	github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.5 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/ini v1.7.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/internal/v4a v1.1.6 // indirect | 	github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.15 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.38 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.15.6 // indirect | 	github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.4 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/sso v1.15.2 // indirect | 	github.com/aws/aws-sdk-go-v2/service/sso v1.17.3 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3 // indirect | 	github.com/aws/aws-sdk-go-v2/service/ssooidc v1.20.1 // indirect | ||||||
| 	github.com/aws/aws-sdk-go-v2/service/sts v1.23.2 // indirect | 	github.com/aws/aws-sdk-go-v2/service/sts v1.25.4 // indirect | ||||||
| 	github.com/aws/smithy-go v1.15.0 // indirect |  | ||||||
| 	github.com/beorn7/perks v1.0.1 // indirect | 	github.com/beorn7/perks v1.0.1 // indirect | ||||||
| 	github.com/bwmarrin/snowflake v0.3.0 // indirect | 	github.com/bwmarrin/snowflake v0.3.0 // indirect | ||||||
| 	github.com/bytedance/sonic v1.10.2 // indirect | 	github.com/bytedance/sonic v1.10.2 // indirect | ||||||
| 	github.com/cespare/xxhash/v2 v2.2.0 // indirect | 	github.com/cespare/xxhash/v2 v2.2.0 // indirect | ||||||
| 	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect | 	github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect | ||||||
| 	github.com/chenzhuoyu/iasm v0.9.0 // indirect | 	github.com/chenzhuoyu/iasm v0.9.1 // indirect | ||||||
| 	github.com/cockroachdb/errors v1.11.1 // indirect | 	github.com/cockroachdb/errors v1.11.1 // indirect | ||||||
| 	github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect | 	github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect | ||||||
| 	github.com/cockroachdb/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect | 	github.com/cockroachdb/pebble v0.0.0-20210331181633-27fc006b8bfb // indirect | ||||||
| 	github.com/cockroachdb/redact v1.1.5 // indirect | 	github.com/cockroachdb/redact v1.1.5 // indirect | ||||||
| 	github.com/emirpasic/gods v1.18.1 // indirect |  | ||||||
| 	github.com/gabriel-vasile/mimetype v1.4.3 // indirect | 	github.com/gabriel-vasile/mimetype v1.4.3 // indirect | ||||||
| 	github.com/getsentry/sentry-go v0.25.0 // indirect | 	github.com/getsentry/sentry-go v0.25.0 // indirect | ||||||
| 	github.com/gin-contrib/sse v0.1.0 // indirect | 	github.com/gin-contrib/sse v0.1.0 // indirect | ||||||
| 	github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect | 	github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect | ||||||
| 	github.com/go-faster/city v1.0.1 // indirect | 	github.com/go-faster/city v1.0.1 // indirect | ||||||
| 	github.com/go-faster/errors v0.6.1 // indirect | 	github.com/go-faster/errors v0.7.0 // indirect | ||||||
| 	github.com/go-logr/logr v1.2.4 // indirect | 	github.com/go-logr/logr v1.3.0 // indirect | ||||||
| 	github.com/go-ole/go-ole v1.2.6 // indirect | 	github.com/go-ole/go-ole v1.2.6 // indirect | ||||||
| 	github.com/go-playground/locales v0.14.1 // indirect | 	github.com/go-playground/locales v0.14.1 // indirect | ||||||
| 	github.com/go-playground/universal-translator v0.18.1 // indirect | 	github.com/go-playground/universal-translator v0.18.1 // indirect | ||||||
| @@ -125,15 +124,15 @@ require ( | |||||||
| 	github.com/google/btree v1.1.2 // indirect | 	github.com/google/btree v1.1.2 // indirect | ||||||
| 	github.com/google/go-cmp v0.6.0 // indirect | 	github.com/google/go-cmp v0.6.0 // indirect | ||||||
| 	github.com/google/go-querystring v1.1.0 // indirect | 	github.com/google/go-querystring v1.1.0 // indirect | ||||||
| 	github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect | 	github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect | ||||||
| 	github.com/google/uuid v1.3.1 // indirect | 	github.com/google/uuid v1.4.0 // indirect | ||||||
| 	github.com/gorilla/css v1.0.0 // indirect | 	github.com/gorilla/css v1.0.1 // indirect | ||||||
| 	github.com/hashicorp/errwrap v1.1.0 // indirect | 	github.com/hashicorp/errwrap v1.1.0 // indirect | ||||||
| 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect | 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect | ||||||
| 	github.com/hashicorp/go-immutable-radix v1.3.1 // indirect | 	github.com/hashicorp/go-immutable-radix v1.3.1 // indirect | ||||||
| 	github.com/hashicorp/go-msgpack v0.5.5 // indirect | 	github.com/hashicorp/go-msgpack v0.5.5 // indirect | ||||||
| 	github.com/hashicorp/go-multierror v1.1.1 // indirect | 	github.com/hashicorp/go-multierror v1.1.1 // indirect | ||||||
| 	github.com/hashicorp/go-sockaddr v1.0.5 // indirect | 	github.com/hashicorp/go-sockaddr v1.0.6 // indirect | ||||||
| 	github.com/hashicorp/golang-lru v1.0.2 // indirect | 	github.com/hashicorp/golang-lru v1.0.2 // indirect | ||||||
| 	github.com/hashicorp/hcl v1.0.0 // indirect | 	github.com/hashicorp/hcl v1.0.0 // indirect | ||||||
| 	github.com/hashicorp/memberlist v0.5.0 // indirect | 	github.com/hashicorp/memberlist v0.5.0 // indirect | ||||||
| @@ -142,32 +141,33 @@ require ( | |||||||
| 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | 	github.com/inconshreveable/mousetrap v1.1.0 // indirect | ||||||
| 	github.com/jackc/pgpassfile v1.0.0 // indirect | 	github.com/jackc/pgpassfile v1.0.0 // indirect | ||||||
| 	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect | 	github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect | ||||||
| 	github.com/jackc/pgx/v5 v5.4.3 // indirect | 	github.com/jackc/pgx/v5 v5.5.0 // indirect | ||||||
|  | 	github.com/jackc/puddle/v2 v2.2.1 // indirect | ||||||
| 	github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect | 	github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect | ||||||
| 	github.com/jinzhu/inflection v1.0.0 // indirect | 	github.com/jinzhu/inflection v1.0.0 // indirect | ||||||
| 	github.com/jinzhu/now v1.1.5 // indirect | 	github.com/jinzhu/now v1.1.5 // indirect | ||||||
| 	github.com/json-iterator/go v1.1.12 // indirect | 	github.com/json-iterator/go v1.1.12 // indirect | ||||||
| 	github.com/juju/ratelimit v1.0.2 // indirect | 	github.com/juju/ratelimit v1.0.2 // indirect | ||||||
| 	github.com/klauspost/compress v1.17.1 // indirect | 	github.com/klauspost/compress v1.17.3 // indirect | ||||||
| 	github.com/klauspost/cpuid/v2 v2.2.5 // indirect | 	github.com/klauspost/cpuid/v2 v2.2.6 // indirect | ||||||
| 	github.com/kr/pretty v0.3.1 // indirect | 	github.com/kr/pretty v0.3.1 // indirect | ||||||
| 	github.com/kr/text v0.2.0 // indirect | 	github.com/kr/text v0.2.0 // indirect | ||||||
| 	github.com/leodido/go-urn v1.2.4 // indirect | 	github.com/leodido/go-urn v1.2.4 // indirect | ||||||
| 	github.com/lni/goutils v1.3.0 // indirect | 	github.com/lni/goutils v1.3.0 // indirect | ||||||
| 	github.com/magiconair/properties v1.8.7 // indirect | 	github.com/magiconair/properties v1.8.7 // indirect | ||||||
| 	github.com/mattn/go-isatty v0.0.19 // indirect | 	github.com/mattn/go-isatty v0.0.20 // indirect | ||||||
| 	github.com/mattn/go-runewidth v0.0.15 // indirect | 	github.com/mattn/go-runewidth v0.0.15 // indirect | ||||||
| 	github.com/mattn/go-sqlite3 v1.14.17 // indirect | 	github.com/mattn/go-sqlite3 v1.14.18 // indirect | ||||||
| 	github.com/mattn/go-tty v0.0.5 // indirect | 	github.com/mattn/go-tty v0.0.5 // indirect | ||||||
| 	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect | 	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect | ||||||
| 	github.com/microsoft/go-mssqldb v1.6.0 // indirect | 	github.com/microsoft/go-mssqldb v1.6.0 // indirect | ||||||
| 	github.com/miekg/dns v1.1.56 // indirect | 	github.com/miekg/dns v1.1.57 // indirect | ||||||
| 	github.com/minio/highwayhash v1.0.2 // indirect | 	github.com/minio/highwayhash v1.0.2 // indirect | ||||||
| 	github.com/mitchellh/copystructure v1.2.0 // indirect | 	github.com/mitchellh/copystructure v1.2.0 // indirect | ||||||
| 	github.com/mitchellh/reflectwalk v1.0.2 // indirect | 	github.com/mitchellh/reflectwalk v1.0.2 // indirect | ||||||
| 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect | ||||||
| 	github.com/modern-go/reflect2 v1.0.2 // indirect | 	github.com/modern-go/reflect2 v1.0.2 // indirect | ||||||
| 	github.com/nats-io/nkeys v0.4.5 // indirect | 	github.com/nats-io/nkeys v0.4.6 // indirect | ||||||
| 	github.com/nats-io/nuid v1.0.1 // indirect | 	github.com/nats-io/nuid v1.0.1 // indirect | ||||||
| 	github.com/olekukonko/tablewriter v0.0.5 // indirect | 	github.com/olekukonko/tablewriter v0.0.5 // indirect | ||||||
| 	github.com/paulmach/orb v0.10.0 // indirect | 	github.com/paulmach/orb v0.10.0 // indirect | ||||||
| @@ -176,7 +176,7 @@ require ( | |||||||
| 	github.com/pkg/errors v0.9.1 // indirect | 	github.com/pkg/errors v0.9.1 // indirect | ||||||
| 	github.com/pkg/term v1.2.0-beta.2 // indirect | 	github.com/pkg/term v1.2.0-beta.2 // indirect | ||||||
| 	github.com/prometheus/client_model v0.5.0 // indirect | 	github.com/prometheus/client_model v0.5.0 // indirect | ||||||
| 	github.com/prometheus/common v0.44.0 // indirect | 	github.com/prometheus/common v0.45.0 // indirect | ||||||
| 	github.com/prometheus/procfs v0.12.0 // indirect | 	github.com/prometheus/procfs v0.12.0 // indirect | ||||||
| 	github.com/rivo/uniseg v0.4.4 // indirect | 	github.com/rivo/uniseg v0.4.4 // indirect | ||||||
| 	github.com/rogpeppe/go-internal v1.11.0 // indirect | 	github.com/rogpeppe/go-internal v1.11.0 // indirect | ||||||
| @@ -201,15 +201,15 @@ require ( | |||||||
| 	github.com/x448/float16 v0.8.4 // indirect | 	github.com/x448/float16 v0.8.4 // indirect | ||||||
| 	github.com/xujiajun/mmap-go v1.0.1 // indirect | 	github.com/xujiajun/mmap-go v1.0.1 // indirect | ||||||
| 	github.com/yusufpapurcu/wmi v1.2.3 // indirect | 	github.com/yusufpapurcu/wmi v1.2.3 // indirect | ||||||
| 	go.opentelemetry.io/otel v1.19.0 // indirect | 	go.opentelemetry.io/otel v1.21.0 // indirect | ||||||
| 	go.opentelemetry.io/otel/trace v1.19.0 // indirect | 	go.opentelemetry.io/otel/trace v1.21.0 // indirect | ||||||
| 	go.uber.org/multierr v1.11.0 // indirect | 	go.uber.org/multierr v1.11.0 // indirect | ||||||
| 	golang.org/x/arch v0.5.0 // indirect | 	golang.org/x/arch v0.6.0 // indirect | ||||||
| 	golang.org/x/crypto v0.14.0 // indirect | 	golang.org/x/crypto v0.15.0 // indirect | ||||||
| 	golang.org/x/mod v0.13.0 // indirect | 	golang.org/x/mod v0.14.0 // indirect | ||||||
| 	golang.org/x/text v0.13.0 // indirect | 	golang.org/x/text v0.14.0 // indirect | ||||||
| 	golang.org/x/time v0.3.0 // indirect | 	golang.org/x/time v0.4.0 // indirect | ||||||
| 	golang.org/x/tools v0.14.0 // indirect | 	golang.org/x/tools v0.15.0 // indirect | ||||||
| 	google.golang.org/appengine v1.6.8 // indirect | 	google.golang.org/appengine v1.6.8 // indirect | ||||||
| 	google.golang.org/protobuf v1.31.0 // indirect | 	google.golang.org/protobuf v1.31.0 // indirect | ||||||
| 	gopkg.in/ini.v1 v1.67.0 // indirect | 	gopkg.in/ini.v1 v1.67.0 // indirect | ||||||
|   | |||||||
| @@ -93,6 +93,7 @@ func (o *srv) setServer(ctx context.Context) error { | |||||||
|  |  | ||||||
| 	var stdlog = o.logger() | 	var stdlog = o.logger() | ||||||
|  |  | ||||||
|  | 	// #nosec | ||||||
| 	s := &http.Server{ | 	s := &http.Server{ | ||||||
| 		Addr:    bind, | 		Addr:    bind, | ||||||
| 		Handler: o.HandlerLoadFct(), | 		Handler: o.HandlerLoadFct(), | ||||||
|   | |||||||
| @@ -56,6 +56,8 @@ func (o *optServer) initServer(s *http.Server) liberr.Error { | |||||||
|  |  | ||||||
| 	if o.ReadHeaderTimeout > 0 { | 	if o.ReadHeaderTimeout > 0 { | ||||||
| 		s.ReadHeaderTimeout = o.ReadHeaderTimeout | 		s.ReadHeaderTimeout = o.ReadHeaderTimeout | ||||||
|  | 	} else { | ||||||
|  | 		s.ReadHeaderTimeout = 30 * time.Second | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if o.WriteTimeout > 0 { | 	if o.WriteTimeout > 0 { | ||||||
|   | |||||||
| @@ -57,7 +57,11 @@ func PathCheckCreate(isFile bool, path string, permFile os.FileMode, permDir os. | |||||||
| 		return os.MkdirAll(path, permDir) | 		return os.MkdirAll(path, permDir) | ||||||
| 	} else if err = PathCheckCreate(false, filepath.Dir(path), permFile, permDir); err != nil { | 	} else if err = PathCheckCreate(false, filepath.Dir(path), permFile, permDir); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} else if hf, e := os.Create(path); e != nil { | 	} | ||||||
|  |  | ||||||
|  | 	// #nosec | ||||||
|  | 	hf, e := os.Create(path) | ||||||
|  | 	if e != nil { | ||||||
| 		return e | 		return e | ||||||
| 	} else { | 	} else { | ||||||
| 		_ = hf.Close() | 		_ = hf.Close() | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								ldap/ldap.go
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								ldap/ldap.go
									
									
									
									
									
								
							| @@ -72,6 +72,23 @@ func NewLDAP(ctx context.Context, cnf *Config, attributes []string) (*HelperLDAP | |||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (lc *HelperLDAP) Clone() *HelperLDAP { | ||||||
|  | 	var att = make([]string, 0) | ||||||
|  | 	copy(att, lc.Attributes) | ||||||
|  |  | ||||||
|  | 	return &HelperLDAP{ | ||||||
|  | 		Attributes: att, | ||||||
|  | 		conn:       nil, | ||||||
|  | 		config:     lc.config.Clone(), | ||||||
|  | 		tlsConfig:  lc.tlsConfig.Clone(), | ||||||
|  | 		tlsMode:    lc.tlsMode, | ||||||
|  | 		bindDN:     lc.bindDN, | ||||||
|  | 		bindPass:   lc.bindPass, | ||||||
|  | 		ctx:        lc.ctx, | ||||||
|  | 		log:        lc.log, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetLogger is used to specify the logger to be used for debug messgae | // SetLogger is used to specify the logger to be used for debug messgae | ||||||
| func (lc *HelperLDAP) SetLogger(fct liblog.FuncLog) { | func (lc *HelperLDAP) SetLogger(fct liblog.FuncLog) { | ||||||
| 	lc.log = fct | 	lc.log = fct | ||||||
| @@ -242,7 +259,7 @@ func (lc *HelperLDAP) tryConnect() (TLSMode, liberr.Error) { | |||||||
|  |  | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		if l != nil { | 		if l != nil { | ||||||
| 			l.Close() | 			_ = l.Close() | ||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| @@ -306,7 +323,7 @@ func (lc *HelperLDAP) connect() liberr.Error { | |||||||
| 			l, err = lc.dialTLS() | 			l, err = lc.dialTLS() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				if l != nil { | 				if l != nil { | ||||||
| 					l.Close() | 					_ = l.Close() | ||||||
| 				} | 				} | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @@ -316,7 +333,7 @@ func (lc *HelperLDAP) connect() liberr.Error { | |||||||
| 			l, err = lc.dial() | 			l, err = lc.dial() | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				if l != nil { | 				if l != nil { | ||||||
| 					l.Close() | 					_ = l.Close() | ||||||
| 				} | 				} | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @@ -326,7 +343,7 @@ func (lc *HelperLDAP) connect() liberr.Error { | |||||||
| 			err = lc.starttls(l) | 			err = lc.starttls(l) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				if l != nil { | 				if l != nil { | ||||||
| 					l.Close() | 					_ = l.Close() | ||||||
| 				} | 				} | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
| @@ -348,7 +365,7 @@ func (lc *HelperLDAP) Check() liberr.Error { | |||||||
| 	if lc.conn == nil { | 	if lc.conn == nil { | ||||||
| 		defer func() { | 		defer func() { | ||||||
| 			if lc.conn != nil { | 			if lc.conn != nil { | ||||||
| 				lc.conn.Close() | 				_ = lc.conn.Close() | ||||||
| 				lc.conn = nil | 				lc.conn = nil | ||||||
| 			} | 			} | ||||||
| 		}() | 		}() | ||||||
| @@ -369,7 +386,7 @@ func (lc *HelperLDAP) Close() { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if lc.conn != nil { | 	if lc.conn != nil { | ||||||
| 		lc.conn.Close() | 		_ = lc.conn.Close() | ||||||
| 		lc.conn = nil | 		lc.conn = nil | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -99,7 +99,10 @@ func New(opt logcfg.OptionsFile, format logrus.Formatter) (HookFile, error) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if h, e := os.OpenFile(opt.Filepath, flags, opt.FileMode); e != nil { | 	// #nosec | ||||||
|  | 	h, e := os.OpenFile(opt.Filepath, flags, opt.FileMode) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return nil, e | 		return nil, e | ||||||
| 	} else if _, e = h.Seek(0, io.SeekEnd); e != nil { | 	} else if _, e = h.Seek(0, io.SeekEnd); e != nil { | ||||||
| 		_ = h.Close() | 		_ = h.Close() | ||||||
|   | |||||||
| @@ -74,7 +74,10 @@ func (o *hkf) writeBuffer(buf *bytes.Buffer) error { | |||||||
| 		} | 		} | ||||||
| 	}() | 	}() | ||||||
|  |  | ||||||
| 	if h, e = os.OpenFile(p, f, m); e != nil { | 	// #nosec | ||||||
|  | 	h, e = os.OpenFile(p, f, m) | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
| 		return e | 		return e | ||||||
| 	} else if _, e = h.Seek(0, io.SeekEnd); e != nil { | 	} else if _, e = h.Seek(0, io.SeekEnd); e != nil { | ||||||
| 		return e | 		return e | ||||||
|   | |||||||
| @@ -104,6 +104,7 @@ func (c Config) LogConfigJson() liberr.Error { | |||||||
| 		return ErrorConfigInvalidFilePath.Error(e) | 		return ErrorConfigInvalidFilePath.Error(e) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// #nosec | ||||||
| 	f, e := os.OpenFile(c.Logs.LogFile, os.O_APPEND|os.O_WRONLY, permFile) | 	f, e := os.OpenFile(c.Logs.LogFile, os.O_APPEND|os.O_WRONLY, permFile) | ||||||
| 	if e != nil { | 	if e != nil { | ||||||
| 		return ErrorConfigInvalidFilePath.Error(e) | 		return ErrorConfigInvalidFilePath.Error(e) | ||||||
| @@ -1054,6 +1055,7 @@ func (c ConfigWebsocket) makeOpt(defTls libtls.TLSConfig) (natsrv.WebsocketOpts, | |||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		cfg.NoTLS = true | 		cfg.NoTLS = true | ||||||
|  | 		// #nosec | ||||||
| 		cfg.TLSConfig = &tls.Config{} | 		cfg.TLSConfig = &tls.Config{} | ||||||
| 		cfg.HandshakeTimeout = 0 | 		cfg.HandshakeTimeout = 0 | ||||||
| 	} | 	} | ||||||
| @@ -1092,6 +1094,7 @@ func (c ConfigMQTT) makeOpt(defTls libtls.TLSConfig) (natsrv.MQTTOpts, liberr.Er | |||||||
| 			cfg.TLSTimeout = float64(c.TLSTimeout) / float64(time.Second) | 			cfg.TLSTimeout = float64(c.TLSTimeout) / float64(time.Second) | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
|  | 		// #nosec | ||||||
| 		cfg.TLSConfig = &tls.Config{} | 		cfg.TLSConfig = &tls.Config{} | ||||||
| 		cfg.TLSTimeout = 0 | 		cfg.TLSTimeout = 0 | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -28,12 +28,19 @@ | |||||||
| package protocol | package protocol | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  |  | ||||||
| 	"gopkg.in/yaml.v3" | 	"gopkg.in/yaml.v3" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	dblQuote = "\"" | ||||||
|  | 	smpQuote = "'" | ||||||
|  | ) | ||||||
|  |  | ||||||
| func (s *NetworkProtocol) unmarshall(val []byte) error { | func (s *NetworkProtocol) unmarshall(val []byte) error { | ||||||
|  | 	val = bytes.Trim(bytes.Trim(val, smpQuote), dblQuote) | ||||||
| 	*s = ParseBytes(val) | 	*s = ParseBytes(val) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,8 +26,8 @@ | |||||||
| package password | package password | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"math/rand" | 	"crypto/rand" | ||||||
| 	"time" | 	"math/big" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const letterBytes = "abcdefghijklmnopqrstuvwxyz,;:!?./*%^$&\"'(-_)=+~#{[|`\\^@]}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | const letterBytes = "abcdefghijklmnopqrstuvwxyz,;:!?./*%^$&\"'(-_)=+~#{[|`\\^@]}ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" | ||||||
| @@ -41,36 +41,32 @@ const ( | |||||||
| 	loopRandMaxLen = 10 | 	loopRandMaxLen = 10 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func randStringBytesMaskImprSrc(n int) string { | func randIdx() int { | ||||||
| 	var src = rand.NewSource(time.Now().UnixNano()) | 	size := int64(len(letterBytes)) | ||||||
|  |  | ||||||
|  | 	for n := 0; n < 100; n++ { | ||||||
|  |  | ||||||
|  | 		if i, e := rand.Int(rand.Reader, big.NewInt(size+1)); e != nil { | ||||||
|  | 			return 0 | ||||||
|  | 		} else { | ||||||
|  | 			j := i.Int64() | ||||||
|  |  | ||||||
|  | 			if j > 0 && j < size { | ||||||
|  | 				return int(j) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func Generate(n int) string { | ||||||
| 	b := make([]byte, n) | 	b := make([]byte, n) | ||||||
| 	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters! | 	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters! | ||||||
| 	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; { | 	for i := n - 1; i >= 0; { | ||||||
| 		if remain == 0 { | 		b[i] = letterBytes[randIdx()] | ||||||
| 			cache, remain = src.Int63(), letterIdxMax |  | ||||||
| 		} |  | ||||||
| 		if idx := int(cache & letterIdxMask); idx < len(letterBytes) { |  | ||||||
| 			b[i] = letterBytes[idx] |  | ||||||
| 		i-- | 		i-- | ||||||
| 	} | 	} | ||||||
| 		cache >>= letterIdxBits |  | ||||||
| 		remain-- |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return string(b) | 	return string(b) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Generate Generate a random string could be used as password. |  | ||||||
| // The len is defined by given 'n' parameters. |  | ||||||
| func Generate(n int) string { |  | ||||||
| 	if n > loopRandMaxLen { |  | ||||||
| 		var s = "" |  | ||||||
| 		for i := n; i > 0; i -= loopRandMaxLen { |  | ||||||
| 			s += randStringBytesMaskImprSrc(loopRandMaxLen) |  | ||||||
| 		} |  | ||||||
| 		return s[0 : n-1] |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return randStringBytesMaskImprSrc(n) |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -41,7 +41,8 @@ const ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	_maxFloat = uint64(math.Ceil(math.MaxFloat64)) | 	_maxFloat64 = uint64(math.Ceil(math.MaxFloat64)) | ||||||
|  | 	_maxFloat32 = uint64(math.Ceil(math.MaxFloat32)) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (s Size) String() string { | func (s Size) String() string { | ||||||
| @@ -63,12 +64,48 @@ func (s Size) Int64() int64 { | |||||||
| 	return int64(s) | 	return int64(s) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s Size) Int32() int32 { | ||||||
|  | 	if uint64(s) > math.MaxInt32 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxInt32 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int32(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s Size) Int() int { | ||||||
|  | 	if uint64(s) > math.MaxInt { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxInt | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return int(s) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s Size) Uint64() uint64 { | func (s Size) Uint64() uint64 { | ||||||
| 	return uint64(s) | 	return uint64(s) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s Size) Uint32() uint32 { | ||||||
|  | 	if uint64(s) > math.MaxUint32 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxUint32 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return uint32(s) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s Size) Uint() uint { | ||||||
|  | 	if uint64(s) > math.MaxUint { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxUint | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return uint(s) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s Size) Float64() float64 { | func (s Size) Float64() float64 { | ||||||
| 	if uint64(s) > _maxFloat { | 	if uint64(s) > _maxFloat64 { | ||||||
| 		// overflow | 		// overflow | ||||||
| 		return math.MaxFloat64 | 		return math.MaxFloat64 | ||||||
| 	} | 	} | ||||||
| @@ -76,6 +113,15 @@ func (s Size) Float64() float64 { | |||||||
| 	return float64(s) | 	return float64(s) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s Size) Float32() float32 { | ||||||
|  | 	if uint64(s) > _maxFloat32 { | ||||||
|  | 		// overflow | ||||||
|  | 		return math.MaxFloat32 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return float32(s) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s Size) Format(format string) string { | func (s Size) Format(format string) string { | ||||||
| 	switch { | 	switch { | ||||||
| 	case SizeExa.isMax(s): | 	case SizeExa.isMax(s): | ||||||
|   | |||||||
| @@ -27,6 +27,8 @@ | |||||||
|  |  | ||||||
| package bytes | package bytes | ||||||
|  |  | ||||||
|  | import "math" | ||||||
|  |  | ||||||
| type Size uint64 | type Size uint64 | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -65,6 +67,18 @@ func SizeFromInt64(val int64) Size { | |||||||
| 	return Size(v) | 	return Size(v) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func SizeFromFloat64(val float64) Size { | ||||||
|  | 	val = math.Floor(val) | ||||||
|  |  | ||||||
|  | 	if val > math.MaxUint64 { | ||||||
|  | 		return Size(uint64(math.MaxUint64)) | ||||||
|  | 	} else if -val > math.MaxUint64 { | ||||||
|  | 		return Size(uint64(math.MaxUint64)) | ||||||
|  | 	} else { | ||||||
|  | 		return Size(uint64(val)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func Parse(s string) (Size, error) { | func Parse(s string) (Size, error) { | ||||||
| 	return parseString(s) | 	return parseString(s) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -69,10 +69,10 @@ func (s Size) isMax(size Size) bool { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s Size) sizeByUnit(unit Size) float64 { | func (s Size) sizeByUnit(unit Size) float64 { | ||||||
| 	if s > 0 && uint64(s/unit) > _maxFloat { | 	if s > 0 && uint64(s/unit) > _maxFloat64 { | ||||||
| 		// overflow | 		// overflow | ||||||
| 		return math.MaxFloat64 | 		return math.MaxFloat64 | ||||||
| 	} else if s < 0 && uint64(-s/unit) > _maxFloat { | 	} else if s < 0 && uint64(-s/unit) > _maxFloat64 { | ||||||
| 		// overflow | 		// overflow | ||||||
| 		return -math.MaxFloat64 | 		return -math.MaxFloat64 | ||||||
| 	} else { | 	} else { | ||||||
|   | |||||||
| @@ -28,9 +28,10 @@ package config | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"os" | 	"os" | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
|  | 	libdur "github.com/nabbar/golib/duration" | ||||||
| 	libptc "github.com/nabbar/golib/network/protocol" | 	libptc "github.com/nabbar/golib/network/protocol" | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| 	scksrv "github.com/nabbar/golib/socket/server" | 	scksrv "github.com/nabbar/golib/socket/server" | ||||||
| ) | ) | ||||||
| @@ -39,17 +40,17 @@ type ServerConfig struct { | |||||||
| 	Network      libptc.NetworkProtocol `` | 	Network      libptc.NetworkProtocol `` | ||||||
| 	Address      string | 	Address      string | ||||||
| 	PermFile     os.FileMode | 	PermFile     os.FileMode | ||||||
| 	BuffSizeRead int32 | 	BuffSizeRead libsiz.Size | ||||||
| 	TimeoutRead  time.Duration | 	TimeoutRead  libdur.Duration | ||||||
| 	TimeoutWrite time.Duration | 	TimeoutWrite libdur.Duration | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o ServerConfig) New(handler libsck.Handler) (libsck.Server, error) { | func (o ServerConfig) New(handler libsck.Handler) (libsck.Server, error) { | ||||||
| 	s, e := scksrv.New(handler, o.Network, o.BuffSizeRead, o.Address, o.PermFile) | 	s, e := scksrv.New(handler, o.Network, o.BuffSizeRead, o.Address, o.PermFile) | ||||||
|  |  | ||||||
| 	if e != nil { | 	if e != nil { | ||||||
| 		s.SetReadTimeout(o.TimeoutRead) | 		s.SetReadTimeout(o.TimeoutRead.Time()) | ||||||
| 		s.SetWriteTimeout(o.TimeoutWrite) | 		s.SetWriteTimeout(o.TimeoutWrite.Time()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return s, e | 	return s, e | ||||||
|   | |||||||
| @@ -31,6 +31,8 @@ import ( | |||||||
| 	"io" | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	libtls "github.com/nabbar/golib/certificates" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const DefaultBufferSize = 32 * 1024 | const DefaultBufferSize = 32 * 1024 | ||||||
| @@ -48,7 +50,31 @@ const ( | |||||||
| 	ConnectionClose | 	ConnectionClose | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | func (c ConnState) String() string { | ||||||
|  | 	switch c { | ||||||
|  | 	case ConnectionDial: | ||||||
|  | 		return "Dial Connection" | ||||||
|  | 	case ConnectionNew: | ||||||
|  | 		return "New Connection" | ||||||
|  | 	case ConnectionRead: | ||||||
|  | 		return "Read Incoming Stream" | ||||||
|  | 	case ConnectionCloseRead: | ||||||
|  | 		return "Close Incoming Stream" | ||||||
|  | 	case ConnectionHandler: | ||||||
|  | 		return "Run Handler" | ||||||
|  | 	case ConnectionWrite: | ||||||
|  | 		return "Write Outgoing Steam" | ||||||
|  | 	case ConnectionCloseWrite: | ||||||
|  | 		return "Close Outgoing Stream" | ||||||
|  | 	case ConnectionClose: | ||||||
|  | 		return "Close Connection" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return "unknown connection state" | ||||||
|  | } | ||||||
|  |  | ||||||
| type FuncError func(e error) | type FuncError func(e error) | ||||||
|  | type FuncInfoSrv func(msg string) | ||||||
| type FuncInfo func(local, remote net.Addr, state ConnState) | type FuncInfo func(local, remote net.Addr, state ConnState) | ||||||
| type Handler func(request io.Reader, response io.Writer) | type Handler func(request io.Reader, response io.Writer) | ||||||
| type Response func(r io.Reader) | type Response func(r io.Reader) | ||||||
| @@ -56,10 +82,12 @@ type Response func(r io.Reader) | |||||||
| type Server interface { | type Server interface { | ||||||
| 	RegisterFuncError(f FuncError) | 	RegisterFuncError(f FuncError) | ||||||
| 	RegisterFuncInfo(f FuncInfo) | 	RegisterFuncInfo(f FuncInfo) | ||||||
|  | 	RegisterFuncInfoServer(f FuncInfoSrv) | ||||||
|  |  | ||||||
| 	SetReadTimeout(d time.Duration) | 	SetReadTimeout(d time.Duration) | ||||||
| 	SetWriteTimeout(d time.Duration) | 	SetWriteTimeout(d time.Duration) | ||||||
|  |  | ||||||
|  | 	SetTLS(enable bool, config libtls.TLSConfig) error | ||||||
| 	Listen(ctx context.Context) error | 	Listen(ctx context.Context) error | ||||||
| 	Shutdown() | 	Shutdown() | ||||||
| 	Done() <-chan struct{} | 	Done() <-chan struct{} | ||||||
|   | |||||||
| @@ -36,13 +36,14 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	libptc "github.com/nabbar/golib/network/protocol" | 	libptc "github.com/nabbar/golib/network/protocol" | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| 	scksrt "github.com/nabbar/golib/socket/server/tcp" | 	scksrt "github.com/nabbar/golib/socket/server/tcp" | ||||||
| 	scksru "github.com/nabbar/golib/socket/server/udp" | 	scksru "github.com/nabbar/golib/socket/server/udp" | ||||||
| 	scksrx "github.com/nabbar/golib/socket/server/unix" | 	scksrx "github.com/nabbar/golib/socket/server/unix" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead int32, address string, perm os.FileMode) (libsck.Server, error) { | func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead libsiz.Size, address string, perm os.FileMode) (libsck.Server, error) { | ||||||
| 	switch proto { | 	switch proto { | ||||||
| 	case libptc.NetworkUnix: | 	case libptc.NetworkUnix: | ||||||
| 		if strings.EqualFold(runtime.GOOS, "linux") { | 		if strings.EqualFold(runtime.GOOS, "linux") { | ||||||
|   | |||||||
| @@ -34,12 +34,13 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
|  |  | ||||||
| 	libptc "github.com/nabbar/golib/network/protocol" | 	libptc "github.com/nabbar/golib/network/protocol" | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| 	scksrt "github.com/nabbar/golib/socket/server/tcp" | 	scksrt "github.com/nabbar/golib/socket/server/tcp" | ||||||
| 	scksru "github.com/nabbar/golib/socket/server/udp" | 	scksru "github.com/nabbar/golib/socket/server/udp" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead int32, address string, perm os.FileMode) (libsck.Server, error) { | func New(handler libsck.Handler, proto libptc.NetworkProtocol, sizeBufferRead libsiz.Size, address string, perm os.FileMode) (libsck.Server, error) { | ||||||
| 	switch proto { | 	switch proto { | ||||||
| 	case libptc.NetworkTCP, libptc.NetworkTCP4, libptc.NetworkTCP6: | 	case libptc.NetworkTCP, libptc.NetworkTCP4, libptc.NetworkTCP6: | ||||||
| 		s := scksrt.New(handler, sizeBufferRead) | 		s := scksrt.New(handler, sizeBufferRead) | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ package tcp | |||||||
| import ( | import ( | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
|  |  | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -37,7 +38,7 @@ type ServerTcp interface { | |||||||
| 	RegisterServer(address string) error | 	RegisterServer(address string) error | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(h libsck.Handler, sizeBuffRead int32) ServerTcp { | func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerTcp { | ||||||
| 	c := new(atomic.Value) | 	c := new(atomic.Value) | ||||||
| 	c.Store(make(chan []byte)) | 	c.Store(make(chan []byte)) | ||||||
|  |  | ||||||
| @@ -48,17 +49,20 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerTcp { | |||||||
| 	f.Store(h) | 	f.Store(h) | ||||||
|  |  | ||||||
| 	sr := new(atomic.Int32) | 	sr := new(atomic.Int32) | ||||||
| 	sr.Store(sizeBuffRead) | 	sr.Store(sizeBuffRead.Int32()) | ||||||
|  |  | ||||||
| 	return &srv{ | 	return &srv{ | ||||||
| 		l:  nil, | 		l:  nil, | ||||||
|  | 		t:  new(atomic.Value), | ||||||
| 		h:  f, | 		h:  f, | ||||||
| 		c:  c, | 		c:  c, | ||||||
| 		s:  s, | 		s:  s, | ||||||
| 		e:  new(atomic.Value), | 		fe: new(atomic.Value), | ||||||
| 		i:  new(atomic.Value), | 		fi: new(atomic.Value), | ||||||
|  | 		fs: new(atomic.Value), | ||||||
| 		tr: new(atomic.Value), | 		tr: new(atomic.Value), | ||||||
| 		tw: new(atomic.Value), | 		tw: new(atomic.Value), | ||||||
| 		sr: sr, | 		sr: sr, | ||||||
|  | 		ad: new(atomic.Value), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ package tcp | |||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"crypto/tls" | ||||||
| 	"io" | 	"io" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| @@ -83,7 +84,16 @@ func (o *srv) Listen(ctx context.Context) error { | |||||||
|  |  | ||||||
| 	if a == nil { | 	if a == nil { | ||||||
| 		return ErrInvalidAddress | 		return ErrInvalidAddress | ||||||
| 	} else if l, e = net.Listen(libptc.NetworkTCP.Code(), a.Host); e != nil { | 	} else if t := o.getTLS(); t == nil { | ||||||
|  | 		o.fctInfoSrv("starting listening socket '%s %s'", libptc.NetworkTCP.String(), a.Host) | ||||||
|  | 		l, e = net.Listen(libptc.NetworkTCP.Code(), a.Host) | ||||||
|  | 	} else { | ||||||
|  | 		o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkTCP.String(), a.Host) | ||||||
|  | 		l, e = tls.Listen(libptc.NetworkTCP.Code(), a.Host, t) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if e != nil { | ||||||
|  | 		o.fctError(e) | ||||||
| 		return e | 		return e | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -27,12 +27,15 @@ | |||||||
| package tcp | package tcp | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"crypto/tls" | ||||||
|  | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	libtls "github.com/nabbar/golib/certificates" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -45,14 +48,21 @@ func init() { | |||||||
| 	close(closedChanStruct) | 	close(closedChanStruct) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type data struct { | ||||||
|  | 	data any | ||||||
|  | } | ||||||
|  |  | ||||||
| type srv struct { | type srv struct { | ||||||
| 	l net.Listener | 	l net.Listener | ||||||
|  |  | ||||||
|  | 	t *atomic.Value // tls config | ||||||
| 	h *atomic.Value // handler | 	h *atomic.Value // handler | ||||||
| 	c *atomic.Value // chan []byte | 	c *atomic.Value // chan []byte | ||||||
| 	s *atomic.Value // chan struct{} | 	s *atomic.Value // chan struct{} | ||||||
| 	e *atomic.Value // function error |  | ||||||
| 	i *atomic.Value // function info | 	fe *atomic.Value // function error | ||||||
|  | 	fi *atomic.Value // function info | ||||||
|  | 	fs *atomic.Value // function info server | ||||||
|  |  | ||||||
| 	tr *atomic.Value // connection read timeout | 	tr *atomic.Value // connection read timeout | ||||||
| 	tw *atomic.Value // connection write timeout | 	tw *atomic.Value // connection write timeout | ||||||
| @@ -81,12 +91,31 @@ func (o *srv) Shutdown() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error { | ||||||
|  | 	if !enable { | ||||||
|  | 		// #nosec | ||||||
|  | 		o.t.Store(&tls.Config{}) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if config == nil { | ||||||
|  | 		return fmt.Errorf("invalid tls config") | ||||||
|  | 	} else if l := config.GetCertificatePair(); len(l) < 1 { | ||||||
|  | 		return fmt.Errorf("invalid tls config, missing certificates pair") | ||||||
|  | 	} else if t := config.TlsConfig(""); t == nil { | ||||||
|  | 		return fmt.Errorf("invalid tls config") | ||||||
|  | 	} else { | ||||||
|  | 		o.t.Store(t) | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncError(f libsck.FuncError) { | func (o *srv) RegisterFuncError(f libsck.FuncError) { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.e.Store(f) | 	o.fe.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | ||||||
| @@ -94,7 +123,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.i.Store(f) | 	o.fi.Store(f) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	o.fs.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) SetReadTimeout(d time.Duration) { | func (o *srv) SetReadTimeout(d time.Duration) { | ||||||
| @@ -137,7 +174,7 @@ func (o *srv) fctError(e error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.e.Load() | 	v := o.fe.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncError)(e) | 		v.(libsck.FuncError)(e) | ||||||
| 	} | 	} | ||||||
| @@ -148,12 +185,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.i.Load() | 	v := o.fi.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncInfo)(local, remote, state) | 		v.(libsck.FuncInfo)(local, remote, state) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) fctInfoSrv(msg string, args ...interface{}) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	v := o.fs.Load() | ||||||
|  | 	if v != nil { | ||||||
|  | 		v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) handler() libsck.Handler { | func (o *srv) handler() libsck.Handler { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil | 		return nil | ||||||
| @@ -166,3 +214,17 @@ func (o *srv) handler() libsck.Handler { | |||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) getTLS() *tls.Config { | ||||||
|  | 	i := o.t.Load() | ||||||
|  |  | ||||||
|  | 	if i == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} else if t, k := i.(*tls.Config); !k { | ||||||
|  | 		return nil | ||||||
|  | 	} else if len(t.Certificates) < 1 { | ||||||
|  | 		return nil | ||||||
|  | 	} else { | ||||||
|  | 		return t | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -29,6 +29,7 @@ package udp | |||||||
| import ( | import ( | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
|  |  | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -37,7 +38,7 @@ type ServerTcp interface { | |||||||
| 	RegisterServer(address string) error | 	RegisterServer(address string) error | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(h libsck.Handler, sizeBuffRead int32) ServerTcp { | func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerTcp { | ||||||
| 	c := new(atomic.Value) | 	c := new(atomic.Value) | ||||||
| 	c.Store(make(chan []byte)) | 	c.Store(make(chan []byte)) | ||||||
|  |  | ||||||
| @@ -48,17 +49,19 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerTcp { | |||||||
| 	f.Store(h) | 	f.Store(h) | ||||||
|  |  | ||||||
| 	sr := new(atomic.Int32) | 	sr := new(atomic.Int32) | ||||||
| 	sr.Store(sizeBuffRead) | 	sr.Store(sizeBuffRead.Int32()) | ||||||
|  |  | ||||||
| 	return &srv{ | 	return &srv{ | ||||||
| 		l:  nil, | 		l:  nil, | ||||||
| 		h:  f, | 		h:  f, | ||||||
| 		c:  c, | 		c:  c, | ||||||
| 		s:  s, | 		s:  s, | ||||||
| 		e:  new(atomic.Value), | 		fe: new(atomic.Value), | ||||||
| 		i:  new(atomic.Value), | 		fi: new(atomic.Value), | ||||||
|  | 		fs: new(atomic.Value), | ||||||
| 		tr: new(atomic.Value), | 		tr: new(atomic.Value), | ||||||
| 		tw: new(atomic.Value), | 		tw: new(atomic.Value), | ||||||
| 		sr: sr, | 		sr: sr, | ||||||
|  | 		ad: new(atomic.Value), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -93,6 +93,7 @@ func (o *srv) Listen(ctx context.Context) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkUDP.String(), a.Host) | ||||||
| 	defer fctClose() | 	defer fctClose() | ||||||
|  |  | ||||||
| 	// Accept new connection or stop if context or shutdown trigger | 	// Accept new connection or stop if context or shutdown trigger | ||||||
|   | |||||||
| @@ -27,12 +27,14 @@ | |||||||
| package udp | package udp | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
| 	"net/url" | 	"net/url" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	libtls "github.com/nabbar/golib/certificates" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -51,8 +53,10 @@ type srv struct { | |||||||
| 	h *atomic.Value // handler | 	h *atomic.Value // handler | ||||||
| 	c *atomic.Value // chan []byte | 	c *atomic.Value // chan []byte | ||||||
| 	s *atomic.Value // chan struct{} | 	s *atomic.Value // chan struct{} | ||||||
| 	e *atomic.Value // function error |  | ||||||
| 	i *atomic.Value // function info | 	fe *atomic.Value // function error | ||||||
|  | 	fi *atomic.Value // function info | ||||||
|  | 	fs *atomic.Value // function info server | ||||||
|  |  | ||||||
| 	tr *atomic.Value // connection read timeout | 	tr *atomic.Value // connection read timeout | ||||||
| 	tw *atomic.Value // connection write timeout | 	tw *atomic.Value // connection write timeout | ||||||
| @@ -81,12 +85,16 @@ func (o *srv) Shutdown() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncError(f libsck.FuncError) { | func (o *srv) RegisterFuncError(f libsck.FuncError) { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.e.Store(f) | 	o.fe.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | ||||||
| @@ -94,7 +102,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.i.Store(f) | 	o.fi.Store(f) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	o.fs.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) SetReadTimeout(d time.Duration) { | func (o *srv) SetReadTimeout(d time.Duration) { | ||||||
| @@ -137,7 +153,7 @@ func (o *srv) fctError(e error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.e.Load() | 	v := o.fe.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncError)(e) | 		v.(libsck.FuncError)(e) | ||||||
| 	} | 	} | ||||||
| @@ -148,12 +164,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.i.Load() | 	v := o.fi.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncInfo)(local, remote, state) | 		v.(libsck.FuncInfo)(local, remote, state) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) fctInfoSrv(msg string, args ...interface{}) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	v := o.fs.Load() | ||||||
|  | 	if v != nil { | ||||||
|  | 		v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) handler() libsck.Handler { | func (o *srv) handler() libsck.Handler { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil | 		return nil | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ import ( | |||||||
| 	"os" | 	"os" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
|  |  | ||||||
|  | 	libsiz "github.com/nabbar/golib/size" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -41,7 +42,7 @@ type ServerUnix interface { | |||||||
| 	RegisterSocket(unixFile string, perm os.FileMode) | 	RegisterSocket(unixFile string, perm os.FileMode) | ||||||
| } | } | ||||||
|  |  | ||||||
| func New(h libsck.Handler, sizeBuffRead int32) ServerUnix { | func New(h libsck.Handler, sizeBuffRead libsiz.Size) ServerUnix { | ||||||
| 	c := new(atomic.Value) | 	c := new(atomic.Value) | ||||||
| 	c.Store(make(chan []byte)) | 	c.Store(make(chan []byte)) | ||||||
|  |  | ||||||
| @@ -51,26 +52,30 @@ func New(h libsck.Handler, sizeBuffRead int32) ServerUnix { | |||||||
| 	f := new(atomic.Value) | 	f := new(atomic.Value) | ||||||
| 	f.Store(h) | 	f.Store(h) | ||||||
|  |  | ||||||
|  | 	// socket read buff size | ||||||
| 	sr := new(atomic.Int32) | 	sr := new(atomic.Int32) | ||||||
| 	sr.Store(sizeBuffRead) | 	sr.Store(sizeBuffRead.Int32()) | ||||||
|  |  | ||||||
| 	fp := new(atomic.Value) | 	// socket file | ||||||
| 	fp.Store("") | 	sf := new(atomic.Value) | ||||||
|  | 	sf.Store("") | ||||||
|  |  | ||||||
| 	pe := new(atomic.Int64) | 	// socket permission | ||||||
| 	pe.Store(0) | 	sp := new(atomic.Int64) | ||||||
|  | 	sp.Store(0) | ||||||
|  |  | ||||||
| 	return &srv{ | 	return &srv{ | ||||||
| 		l:  nil, | 		l:  nil, | ||||||
| 		h:  f, | 		h:  f, | ||||||
| 		c:  c, | 		c:  c, | ||||||
| 		s:  s, | 		s:  s, | ||||||
| 		e:  new(atomic.Value), | 		fe: new(atomic.Value), | ||||||
| 		i:  new(atomic.Value), | 		fi: new(atomic.Value), | ||||||
|  | 		fs: new(atomic.Value), | ||||||
| 		tr: new(atomic.Value), | 		tr: new(atomic.Value), | ||||||
| 		tw: new(atomic.Value), | 		tw: new(atomic.Value), | ||||||
| 		sr: sr, | 		sr: sr, | ||||||
| 		fs: fp, | 		sf: sf, | ||||||
| 		fp: pe, | 		sp: sp, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ func (o *srv) buffRead() *bytes.Buffer { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) getSocketFile() (string, error) { | func (o *srv) getSocketFile() (string, error) { | ||||||
| 	f := o.fs.Load() | 	f := o.sf.Load() | ||||||
| 	if f != nil { | 	if f != nil { | ||||||
| 		return o.checkFile(f.(string)) | 		return o.checkFile(f.(string)) | ||||||
| 	} | 	} | ||||||
| @@ -91,7 +91,7 @@ func (o *srv) getSocketFile() (string, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) getSocketPerm() os.FileMode { | func (o *srv) getSocketPerm() os.FileMode { | ||||||
| 	p := o.fp.Load() | 	p := o.sp.Load() | ||||||
| 	if p > 0 { | 	if p > 0 { | ||||||
| 		return os.FileMode(p) | 		return os.FileMode(p) | ||||||
| 	} | 	} | ||||||
| @@ -149,6 +149,7 @@ func (o *srv) Listen(ctx context.Context) error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	o.fctInfoSrv("starting listening socket 'TLS %s %s'", libptc.NetworkUnix.String(), unixFile) | ||||||
| 	defer fctClose() | 	defer fctClose() | ||||||
|  |  | ||||||
| 	if i.Mode() != perm { | 	if i.Mode() != perm { | ||||||
|   | |||||||
| @@ -30,11 +30,13 @@ | |||||||
| package unix | package unix | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"fmt" | ||||||
| 	"net" | 	"net" | ||||||
| 	"os" | 	"os" | ||||||
| 	"sync/atomic" | 	"sync/atomic" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	libtls "github.com/nabbar/golib/certificates" | ||||||
| 	libsck "github.com/nabbar/golib/socket" | 	libsck "github.com/nabbar/golib/socket" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -53,14 +55,17 @@ type srv struct { | |||||||
| 	h *atomic.Value // handler | 	h *atomic.Value // handler | ||||||
| 	c *atomic.Value // chan []byte | 	c *atomic.Value // chan []byte | ||||||
| 	s *atomic.Value // chan struct{} | 	s *atomic.Value // chan struct{} | ||||||
| 	e *atomic.Value // function error |  | ||||||
| 	i *atomic.Value // function info | 	fe *atomic.Value // function error | ||||||
|  | 	fi *atomic.Value // function info | ||||||
|  | 	fs *atomic.Value // function info server | ||||||
|  |  | ||||||
| 	tr *atomic.Value // connection read timeout | 	tr *atomic.Value // connection read timeout | ||||||
| 	tw *atomic.Value // connection write timeout | 	tw *atomic.Value // connection write timeout | ||||||
| 	sr *atomic.Int32 // read buffer size | 	sr *atomic.Int32 // read buffer size | ||||||
| 	fs *atomic.Value // file unix socket |  | ||||||
| 	fp *atomic.Int64 // file unix perm | 	sf *atomic.Value // file unix socket | ||||||
|  | 	sp *atomic.Int64 // file unix perm | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) Done() <-chan struct{} { | func (o *srv) Done() <-chan struct{} { | ||||||
| @@ -83,12 +88,16 @@ func (o *srv) Shutdown() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) SetTLS(enable bool, config libtls.TLSConfig) error { | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncError(f libsck.FuncError) { | func (o *srv) RegisterFuncError(f libsck.FuncError) { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.e.Store(f) | 	o.fe.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | ||||||
| @@ -96,7 +105,15 @@ func (o *srv) RegisterFuncInfo(f libsck.FuncInfo) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	o.i.Store(f) | 	o.fi.Store(f) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (o *srv) RegisterFuncInfoServer(f libsck.FuncInfoSrv) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	o.fs.Store(f) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) SetReadTimeout(d time.Duration) { | func (o *srv) SetReadTimeout(d time.Duration) { | ||||||
| @@ -116,8 +133,8 @@ func (o *srv) SetWriteTimeout(d time.Duration) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) RegisterSocket(unixFile string, perm os.FileMode) { | func (o *srv) RegisterSocket(unixFile string, perm os.FileMode) { | ||||||
| 	o.fs.Store(unixFile) | 	o.sf.Store(unixFile) | ||||||
| 	o.fp.Store(int64(perm)) | 	o.sp.Store(int64(perm)) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (o *srv) fctError(e error) { | func (o *srv) fctError(e error) { | ||||||
| @@ -125,7 +142,7 @@ func (o *srv) fctError(e error) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.e.Load() | 	v := o.fe.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncError)(e) | 		v.(libsck.FuncError)(e) | ||||||
| 	} | 	} | ||||||
| @@ -136,12 +153,23 @@ func (o *srv) fctInfo(local, remote net.Addr, state libsck.ConnState) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	v := o.i.Load() | 	v := o.fi.Load() | ||||||
| 	if v != nil { | 	if v != nil { | ||||||
| 		v.(libsck.FuncInfo)(local, remote, state) | 		v.(libsck.FuncInfo)(local, remote, state) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (o *srv) fctInfoSrv(msg string, args ...interface{}) { | ||||||
|  | 	if o == nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	v := o.fs.Load() | ||||||
|  | 	if v != nil { | ||||||
|  | 		v.(libsck.FuncInfoSrv)(fmt.Sprintf(msg, args...)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func (o *srv) handler() libsck.Handler { | func (o *srv) handler() libsck.Handler { | ||||||
| 	if o == nil { | 	if o == nil { | ||||||
| 		return nil | 		return nil | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Nicolas JUHEL
					Nicolas JUHEL