vendor: update buildkit to v0.29.0-rc1
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
This commit is contained in:
+9
@@ -0,0 +1,9 @@
|
||||
codecov:
|
||||
notify:
|
||||
after_n_builds: 2
|
||||
|
||||
coverage:
|
||||
status:
|
||||
patch:
|
||||
default:
|
||||
target: 80%
|
||||
+6
-2
@@ -1,2 +1,6 @@
|
||||
secrets.yml
|
||||
coverage.out
|
||||
*.out
|
||||
*.cov
|
||||
.idea
|
||||
.env
|
||||
.mcp.json
|
||||
.claude/
|
||||
|
||||
+11
-18
@@ -2,25 +2,11 @@ version: "2"
|
||||
linters:
|
||||
default: all
|
||||
disable:
|
||||
- cyclop
|
||||
- depguard
|
||||
- errchkjson
|
||||
- errorlint
|
||||
- exhaustruct
|
||||
- forcetypeassert
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
- gochecknoinits
|
||||
- gocognit
|
||||
- godot
|
||||
- gomoddirectives
|
||||
- godox
|
||||
- gosmopolitan
|
||||
- inamedparam
|
||||
- intrange
|
||||
- ireturn
|
||||
- lll
|
||||
- musttag
|
||||
- nestif
|
||||
- exhaustruct
|
||||
- nlreturn
|
||||
- nonamedreturns
|
||||
- noinlineerr
|
||||
@@ -29,7 +15,6 @@ linters:
|
||||
- testpackage
|
||||
- thelper
|
||||
- tparallel
|
||||
- unparam
|
||||
- varnamelen
|
||||
- whitespace
|
||||
- wrapcheck
|
||||
@@ -41,8 +26,15 @@ linters:
|
||||
goconst:
|
||||
min-len: 2
|
||||
min-occurrences: 3
|
||||
cyclop:
|
||||
max-complexity: 20
|
||||
gocyclo:
|
||||
min-complexity: 45
|
||||
min-complexity: 20
|
||||
exhaustive:
|
||||
default-signifies-exhaustive: true
|
||||
default-case-required: true
|
||||
lll:
|
||||
line-length: 180
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
@@ -58,6 +50,7 @@ formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
- gofumpt
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
|
||||
+4
-2
@@ -23,7 +23,9 @@ include:
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
|
||||
advances
|
||||
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
@@ -55,7 +57,7 @@ further defined and clarified by project maintainers.
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at ivan+abuse@flanders.co.nz. All
|
||||
reported by contacting the project team at <ivan+abuse@flanders.co.nz>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
@@ -68,7 +70,7 @@ members of the project's leadership.
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
available at [<http://contributor-covenant.org/version/1/4>][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
# Contributors
|
||||
|
||||
- Repository: ['go-openapi/strfmt']
|
||||
|
||||
| Total Contributors | Total Contributions |
|
||||
| --- | --- |
|
||||
| 40 | 225 |
|
||||
|
||||
| Username | All Time Contribution Count | All Commits |
|
||||
| --- | --- | --- |
|
||||
| @casualjim | 88 | <https://github.com/go-openapi/strfmt/commits?author=casualjim> |
|
||||
| @fredbi | 57 | <https://github.com/go-openapi/strfmt/commits?author=fredbi> |
|
||||
| @youyuanwu | 13 | <https://github.com/go-openapi/strfmt/commits?author=youyuanwu> |
|
||||
| @jlambatl | 9 | <https://github.com/go-openapi/strfmt/commits?author=jlambatl> |
|
||||
| @GlenDC | 5 | <https://github.com/go-openapi/strfmt/commits?author=GlenDC> |
|
||||
| @padamstx | 4 | <https://github.com/go-openapi/strfmt/commits?author=padamstx> |
|
||||
| @dimovnike | 3 | <https://github.com/go-openapi/strfmt/commits?author=dimovnike> |
|
||||
| @carlv-stripe | 3 | <https://github.com/go-openapi/strfmt/commits?author=carlv-stripe> |
|
||||
| @Copilot | 3 | <https://github.com/go-openapi/strfmt/commits?author=Copilot> |
|
||||
| @keramix | 3 | <https://github.com/go-openapi/strfmt/commits?author=keramix> |
|
||||
| @gregmarr | 2 | <https://github.com/go-openapi/strfmt/commits?author=gregmarr> |
|
||||
| @vadorovsky | 2 | <https://github.com/go-openapi/strfmt/commits?author=vadorovsky> |
|
||||
| @Ompluscator | 2 | <https://github.com/go-openapi/strfmt/commits?author=Ompluscator> |
|
||||
| @johnnyg | 2 | <https://github.com/go-openapi/strfmt/commits?author=johnnyg> |
|
||||
| @chakrit | 2 | <https://github.com/go-openapi/strfmt/commits?author=chakrit> |
|
||||
| @bg451 | 2 | <https://github.com/go-openapi/strfmt/commits?author=bg451> |
|
||||
| @aleksandr-vin | 2 | <https://github.com/go-openapi/strfmt/commits?author=aleksandr-vin> |
|
||||
| @ujjwalsh | 1 | <https://github.com/go-openapi/strfmt/commits?author=ujjwalsh> |
|
||||
| @kenjones-cisco | 1 | <https://github.com/go-openapi/strfmt/commits?author=kenjones-cisco> |
|
||||
| @jwalter1-quest | 1 | <https://github.com/go-openapi/strfmt/commits?author=jwalter1-quest> |
|
||||
| @ccoVeille | 1 | <https://github.com/go-openapi/strfmt/commits?author=ccoVeille> |
|
||||
| @tylerb | 1 | <https://github.com/go-openapi/strfmt/commits?author=tylerb> |
|
||||
| @tzneal | 1 | <https://github.com/go-openapi/strfmt/commits?author=tzneal> |
|
||||
| @tklauser | 1 | <https://github.com/go-openapi/strfmt/commits?author=tklauser> |
|
||||
| @SuperQ | 1 | <https://github.com/go-openapi/strfmt/commits?author=SuperQ> |
|
||||
| @srizzling | 1 | <https://github.com/go-openapi/strfmt/commits?author=srizzling> |
|
||||
| @shawnps | 1 | <https://github.com/go-openapi/strfmt/commits?author=shawnps> |
|
||||
| @prashantv | 1 | <https://github.com/go-openapi/strfmt/commits?author=prashantv> |
|
||||
| @krnkl | 1 | <https://github.com/go-openapi/strfmt/commits?author=krnkl> |
|
||||
| @mstoykov | 1 | <https://github.com/go-openapi/strfmt/commits?author=mstoykov> |
|
||||
| @maxatome | 1 | <https://github.com/go-openapi/strfmt/commits?author=maxatome> |
|
||||
| @jerome-laforge | 1 | <https://github.com/go-openapi/strfmt/commits?author=jerome-laforge> |
|
||||
| @justincormack | 1 | <https://github.com/go-openapi/strfmt/commits?author=justincormack> |
|
||||
| @elipavlov | 1 | <https://github.com/go-openapi/strfmt/commits?author=elipavlov> |
|
||||
| @gbjk | 1 | <https://github.com/go-openapi/strfmt/commits?author=gbjk> |
|
||||
| @enesanbar | 1 | <https://github.com/go-openapi/strfmt/commits?author=enesanbar> |
|
||||
| @CodeLingoBot | 1 | <https://github.com/go-openapi/strfmt/commits?author=CodeLingoBot> |
|
||||
| @Kunde21 | 1 | <https://github.com/go-openapi/strfmt/commits?author=Kunde21> |
|
||||
| @bvwells | 1 | <https://github.com/go-openapi/strfmt/commits?author=bvwells> |
|
||||
| @ligustah | 1 | <https://github.com/go-openapi/strfmt/commits?author=ligustah> |
|
||||
|
||||
_this file was generated by the [Contributors GitHub Action](https://github.com/github-community-projects/contributors)_
|
||||
+150
-12
@@ -1,15 +1,61 @@
|
||||
# Strfmt [](https://github.com/go-openapi/strfmt/actions?query=workflow%3A"go+test") [](https://codecov.io/gh/go-openapi/strfmt)
|
||||
[](https://slackin.goswagger.io)
|
||||
[](https://raw.githubusercontent.com/go-openapi/strfmt/master/LICENSE)
|
||||
[](http://godoc.org/github.com/go-openapi/strfmt)
|
||||
[](https://goreportcard.com/report/github.com/go-openapi/strfmt)
|
||||
# strfmt
|
||||
|
||||
<!-- Badges: status -->
|
||||
[![Tests][test-badge]][test-url] [![Coverage][cov-badge]][cov-url] [![CI vuln scan][vuln-scan-badge]][vuln-scan-url] [![CodeQL][codeql-badge]][codeql-url]
|
||||
<!-- Badges: release & docker images -->
|
||||
<!-- Badges: code quality -->
|
||||
<!-- Badges: license & compliance -->
|
||||
[![Release][release-badge]][release-url] [![Go Report Card][gocard-badge]][gocard-url] [![CodeFactor Grade][codefactor-badge]][codefactor-url] [![License][license-badge]][license-url]
|
||||
<!-- Badges: documentation & support -->
|
||||
<!-- Badges: others & stats -->
|
||||
[![GoDoc][godoc-badge]][godoc-url] [![Discord Channel][discord-badge]][discord-url] [![go version][goversion-badge]][goversion-url] ![Top language][top-badge] ![Commits since latest release][commits-badge]
|
||||
|
||||
---
|
||||
|
||||
Golang support for string formats defined by JSON Schema and OpenAPI.
|
||||
|
||||
## Announcements
|
||||
|
||||
* **2025-12-19** : new community chat on discord
|
||||
* a new discord community channel is available to be notified of changes and support users
|
||||
* our venerable Slack channel remains open, and will be eventually discontinued on **2026-03-31**
|
||||
|
||||
You may join the discord community by clicking the invite link on the discord badge (also above). [![Discord Channel][discord-badge]][discord-url]
|
||||
|
||||
Or join our Slack channel: [![Slack Channel][slack-logo]![slack-badge]][slack-url]
|
||||
|
||||
* **2026-03-07** : v0.26.0 **dropped dependency to the mongodb driver**
|
||||
* mongodb users can still use this package without any change
|
||||
* however, we have frozen the back-compatible support for mongodb driver at v2.5.0
|
||||
* users who want to keep-up with future evolutions (possibly incompatible) of this driver
|
||||
can do so by adding a blank import in their program: `import _ "github.com/go-openapi/strfmt/enable/mongodb"`.
|
||||
This will switch the behavior to the actual driver, which remains regularly updated as an independent module.
|
||||
|
||||
## Status
|
||||
|
||||
API is stable.
|
||||
|
||||
## Import this library in your project
|
||||
|
||||
```cmd
|
||||
go get github.com/go-openapi/strfmt
|
||||
```
|
||||
|
||||
## Contents
|
||||
|
||||
This package exposes a registry of data types to support string formats in the go-openapi toolkit.
|
||||
|
||||
strfmt represents a well known string format such as credit card or email. The go toolkit for OpenAPI specifications knows how to deal with those.
|
||||
`strfmt` represents a well known string format such as hostname or email.
|
||||
|
||||
## Supported data formats
|
||||
go-openapi/strfmt follows the swagger 2.0 specification with the following formats
|
||||
This package provides a few extra formats such as credit card (US), color, etc.
|
||||
|
||||
Format types can serialize and deserialize JSON or from a SQL database.
|
||||
|
||||
BSON is also supported (MongoDB).
|
||||
|
||||
### Supported formats
|
||||
|
||||
`go-openapi/strfmt` follows the swagger 2.0 specification with the following formats
|
||||
defined [here](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types).
|
||||
|
||||
It also provides convenient extensions to go-openapi users.
|
||||
@@ -43,7 +89,7 @@ It also provides convenient extensions to go-openapi users.
|
||||
> It does not provide validation for numerical values with swagger format extension for JSON types "number" or
|
||||
> "integer" (e.g. float, double, int32...).
|
||||
|
||||
## Type conversion
|
||||
### Type conversion
|
||||
|
||||
All types defined here are stringers and may be converted to strings with `.String()`.
|
||||
Note that most types defined by this package may be converted directly to string like `string(Email{})`.
|
||||
@@ -51,13 +97,14 @@ Note that most types defined by this package may be converted directly to string
|
||||
`Date` and `DateTime` may be converted directly to `time.Time` like `time.Time(Time{})`.
|
||||
Similarly, you can convert `Duration` to `time.Duration` as in `time.Duration(Duration{})`
|
||||
|
||||
## Using pointers
|
||||
### Using pointers
|
||||
|
||||
The `conv` subpackage provides helpers to convert the types to and from pointers, just like `go-openapi/swag` does
|
||||
with primitive types.
|
||||
|
||||
## Format types
|
||||
Types defined in strfmt expose marshaling and validation capabilities.
|
||||
### Format types
|
||||
|
||||
Types defined in `strfmt` expose marshaling and validation capabilities.
|
||||
|
||||
List of defined types:
|
||||
- Base64
|
||||
@@ -87,6 +134,97 @@ List of defined types:
|
||||
- [UUID7](https://www.rfc-editor.org/rfc/rfc9562.html#name-uuid-version-7)
|
||||
- [ULID](https://github.com/ulid/spec)
|
||||
|
||||
### Database support
|
||||
|
||||
All format types implement the `database/sql` interfaces `sql.Scanner` and `driver.Valuer`,
|
||||
so they work out of the box with Go's standard `database/sql` package and any SQL driver.
|
||||
|
||||
All format types also implement BSON marshaling/unmarshaling for use with MongoDB.
|
||||
By default, a built-in minimal codec is used (compatible with mongo-driver v2.5.0).
|
||||
For full driver support, add `import _ "github.com/go-openapi/strfmt/enable/mongodb"`.
|
||||
|
||||
> **MySQL / MariaDB caveat for `DateTime`:**
|
||||
> The `go-sql-driver/mysql` driver has hard-coded handling for `time.Time` but does not
|
||||
> intercept type redefinitions like `strfmt.DateTime`. As a result, `DateTime.Value()` sends
|
||||
> an RFC 3339 string (e.g. `"2024-06-15T12:30:45.123Z"`) that MySQL/MariaDB rejects for
|
||||
> `DATETIME` columns.
|
||||
>
|
||||
> Workaround: set `strfmt.MarshalFormat` to a MySQL-compatible format such as
|
||||
> `strfmt.ISO8601LocalTime` and normalize to UTC before marshaling:
|
||||
>
|
||||
> ```go
|
||||
> strfmt.MarshalFormat = strfmt.ISO8601LocalTime
|
||||
> strfmt.NormalizeTimeForMarshal = func(t time.Time) time.Time { return t.UTC() }
|
||||
> ```
|
||||
>
|
||||
> See [#174](https://github.com/go-openapi/strfmt/issues/174) for details.
|
||||
|
||||
Integration tests for MongoDB, MariaDB, and PostgreSQL run in CI to verify database roundtrip
|
||||
compatibility for all format types. See [`internal/testintegration/`](internal/testintegration/).
|
||||
|
||||
## Change log
|
||||
|
||||
See <https://github.com/go-openapi/strfmt/releases>
|
||||
|
||||
## References
|
||||
|
||||
<https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md>
|
||||
|
||||
## Licensing
|
||||
|
||||
This library ships under the [SPDX-License-Identifier: Apache-2.0](./LICENSE).
|
||||
|
||||
## Other documentation
|
||||
|
||||
* [All-time contributors](./CONTRIBUTORS.md)
|
||||
* [Contributing guidelines](.github/CONTRIBUTING.md)
|
||||
* [Maintainers documentation](docs/MAINTAINERS.md)
|
||||
* [Code style](docs/STYLE.md)
|
||||
|
||||
## Cutting a new release
|
||||
|
||||
Maintainers can cut a new release by either:
|
||||
|
||||
* running [this workflow](https://github.com/go-openapi/strfmt/actions/workflows/bump-release.yml)
|
||||
* or pushing a semver tag
|
||||
* signed tags are preferred
|
||||
* The tag message is prepended to release notes
|
||||
|
||||
<!-- Badges: status -->
|
||||
[test-badge]: https://github.com/go-openapi/strfmt/actions/workflows/go-test.yml/badge.svg
|
||||
[test-url]: https://github.com/go-openapi/strfmt/actions/workflows/go-test.yml
|
||||
[cov-badge]: https://codecov.io/gh/go-openapi/strfmt/branch/master/graph/badge.svg
|
||||
[cov-url]: https://codecov.io/gh/go-openapi/strfmt
|
||||
[vuln-scan-badge]: https://github.com/go-openapi/strfmt/actions/workflows/scanner.yml/badge.svg
|
||||
[vuln-scan-url]: https://github.com/go-openapi/strfmt/actions/workflows/scanner.yml
|
||||
[codeql-badge]: https://github.com/go-openapi/strfmt/actions/workflows/codeql.yml/badge.svg
|
||||
[codeql-url]: https://github.com/go-openapi/strfmt/actions/workflows/codeql.yml
|
||||
<!-- Badges: release & docker images -->
|
||||
[release-badge]: https://badge.fury.io/gh/go-openapi%2Fstrfmt.svg
|
||||
[release-url]: https://badge.fury.io/gh/go-openapi%2Fstrfmt
|
||||
[gomod-badge]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fstrfmt.svg
|
||||
[gomod-url]: https://badge.fury.io/go/github.com%2Fgo-openapi%2Fstrfmt
|
||||
<!-- Badges: code quality -->
|
||||
[gocard-badge]: https://goreportcard.com/badge/github.com/go-openapi/strfmt
|
||||
[gocard-url]: https://goreportcard.com/report/github.com/go-openapi/strfmt
|
||||
[codefactor-badge]: https://img.shields.io/codefactor/grade/github/go-openapi/strfmt
|
||||
[codefactor-url]: https://www.codefactor.io/repository/github/go-openapi/strfmt
|
||||
<!-- Badges: documentation & support -->
|
||||
[doc-badge]: https://img.shields.io/badge/doc-site-blue?link=https%3A%2F%2Fgoswagger.io%2Fgo-openapi%2F
|
||||
[doc-url]: https://goswagger.io/go-openapi
|
||||
[godoc-badge]: https://pkg.go.dev/badge/github.com/go-openapi/strfmt
|
||||
[godoc-url]: http://pkg.go.dev/github.com/go-openapi/strfmt
|
||||
[slack-logo]: https://a.slack-edge.com/e6a93c1/img/icons/favicon-32.png
|
||||
[slack-badge]: https://img.shields.io/badge/slack-blue?link=https%3A%2F%2Fgoswagger.slack.com%2Farchives%2FC04R30YM
|
||||
[slack-url]: https://goswagger.slack.com/archives/C04R30YMU
|
||||
[discord-badge]: https://img.shields.io/discord/1446918742398341256?logo=discord&label=discord&color=blue
|
||||
[discord-url]: https://discord.gg/FfnFYaC3k5
|
||||
|
||||
<!-- Badges: license & compliance -->
|
||||
[license-badge]: http://img.shields.io/badge/license-Apache%20v2-orange.svg
|
||||
[license-url]: https://github.com/go-openapi/strfmt/?tab=Apache-2.0-1-ov-file#readme
|
||||
<!-- Badges: others & stats -->
|
||||
[goversion-badge]: https://img.shields.io/github/go-mod/go-version/go-openapi/strfmt
|
||||
[goversion-url]: https://github.com/go-openapi/strfmt/blob/master/go.mod
|
||||
[top-badge]: https://img.shields.io/github/languages/top/go-openapi/strfmt
|
||||
[commits-badge]: https://img.shields.io/github/commits-since/go-openapi/strfmt/latest
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# Security Policy
|
||||
|
||||
This policy outlines the commitment and practices of the go-openapi maintainers regarding security.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 0.x | :white_check_mark: |
|
||||
|
||||
## Vulnerability checks in place
|
||||
|
||||
This repository uses automated vulnerability scans, at every merged commit and at least once a week.
|
||||
|
||||
We use:
|
||||
|
||||
* [`GitHub CodeQL`][codeql-url]
|
||||
* [`trivy`][trivy-url]
|
||||
* [`govulncheck`][govulncheck-url]
|
||||
|
||||
Reports are centralized in github security reports and visible only to the maintainers.
|
||||
|
||||
## Reporting a vulnerability
|
||||
|
||||
If you become aware of a security vulnerability that affects the current repository,
|
||||
**please report it privately to the maintainers**
|
||||
rather than opening a publicly visible GitHub issue.
|
||||
|
||||
Please follow the instructions provided by github to [Privately report a security vulnerability][github-guidance-url].
|
||||
|
||||
> [!NOTE]
|
||||
> On Github, navigate to the project's "Security" tab then click on "Report a vulnerability".
|
||||
|
||||
[codeql-url]: https://github.com/github/codeql
|
||||
[trivy-url]: https://trivy.dev/docs/latest/getting-started
|
||||
[govulncheck-url]: https://go.dev/blog/govulncheck
|
||||
[github-guidance-url]: https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability
|
||||
+56
-32
@@ -5,62 +5,62 @@ package strfmt
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
bsonprim "go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
func init() {
|
||||
func init() { //nolint:gochecknoinits // registers bsonobjectid format in the default registry
|
||||
var id ObjectId
|
||||
// register this format in the default registry
|
||||
Default.Add("bsonobjectid", &id, IsBSONObjectID)
|
||||
}
|
||||
|
||||
// IsBSONObjectID returns true when the string is a valid BSON.ObjectId
|
||||
// IsBSONObjectID returns true when the string is a valid BSON [ObjectId].
|
||||
func IsBSONObjectID(str string) bool {
|
||||
_, err := bsonprim.ObjectIDFromHex(str)
|
||||
_, err := objectIDFromHex(str)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// ObjectId represents a BSON object ID (alias to go.mongodb.org/mongo-driver/bson/primitive.ObjectID)
|
||||
// ObjectId represents a BSON object ID (a 12-byte unique identifier).
|
||||
//
|
||||
// swagger:strfmt bsonobjectid
|
||||
type ObjectId bsonprim.ObjectID //nolint:revive
|
||||
// swagger:strfmt bsonobjectid.
|
||||
type ObjectId [12]byte //nolint:revive
|
||||
|
||||
// NewObjectId creates a ObjectId from a Hex String
|
||||
// nilObjectID is the zero-value ObjectId.
|
||||
var nilObjectID ObjectId //nolint:gochecknoglobals // package-level sentinel
|
||||
|
||||
// NewObjectId creates a [ObjectId] from a hexadecimal String.
|
||||
func NewObjectId(hex string) ObjectId { //nolint:revive
|
||||
oid, err := bsonprim.ObjectIDFromHex(hex)
|
||||
oid, err := objectIDFromHex(hex)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ObjectId(oid)
|
||||
return oid
|
||||
}
|
||||
|
||||
// MarshalText turns this instance into text
|
||||
// MarshalText turns this instance into text.
|
||||
func (id ObjectId) MarshalText() ([]byte, error) {
|
||||
oid := bsonprim.ObjectID(id)
|
||||
if oid == bsonprim.NilObjectID {
|
||||
if id == nilObjectID {
|
||||
return nil, nil
|
||||
}
|
||||
return []byte(oid.Hex()), nil
|
||||
return []byte(id.Hex()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText hydrates this instance from text
|
||||
// UnmarshalText hydrates this instance from text.
|
||||
func (id *ObjectId) UnmarshalText(data []byte) error { // validation is performed later on
|
||||
if len(data) == 0 {
|
||||
*id = ObjectId(bsonprim.NilObjectID)
|
||||
*id = nilObjectID
|
||||
return nil
|
||||
}
|
||||
oidstr := string(data)
|
||||
oid, err := bsonprim.ObjectIDFromHex(oidstr)
|
||||
oid, err := objectIDFromHex(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*id = ObjectId(oid)
|
||||
*id = oid
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scan read a value from a database driver
|
||||
// Scan read a value from a database driver.
|
||||
func (id *ObjectId) Scan(raw any) error {
|
||||
var data []byte
|
||||
switch v := raw.(type) {
|
||||
@@ -75,27 +75,36 @@ func (id *ObjectId) Scan(raw any) error {
|
||||
return id.UnmarshalText(data)
|
||||
}
|
||||
|
||||
// Value converts a value to a database driver value
|
||||
// Value converts a value to a database driver value.
|
||||
func (id ObjectId) Value() (driver.Value, error) {
|
||||
return driver.Value(bsonprim.ObjectID(id).Hex()), nil
|
||||
return driver.Value(id.Hex()), nil
|
||||
}
|
||||
|
||||
// Hex returns the hex string representation of the [ObjectId].
|
||||
func (id ObjectId) Hex() string {
|
||||
return hex.EncodeToString(id[:])
|
||||
}
|
||||
|
||||
func (id ObjectId) String() string {
|
||||
return bsonprim.ObjectID(id).Hex()
|
||||
return id.Hex()
|
||||
}
|
||||
|
||||
// MarshalJSON returns the ObjectId as JSON
|
||||
// MarshalJSON returns the [ObjectId] as JSON.
|
||||
func (id ObjectId) MarshalJSON() ([]byte, error) {
|
||||
return bsonprim.ObjectID(id).MarshalJSON()
|
||||
return json.Marshal(id.Hex())
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets the ObjectId from JSON
|
||||
// UnmarshalJSON sets the [ObjectId] from JSON.
|
||||
func (id *ObjectId) UnmarshalJSON(data []byte) error {
|
||||
var obj bsonprim.ObjectID
|
||||
if err := obj.UnmarshalJSON(data); err != nil {
|
||||
var hexStr string
|
||||
if err := json.Unmarshal(data, &hexStr); err != nil {
|
||||
return err
|
||||
}
|
||||
*id = ObjectId(obj)
|
||||
oid, err := objectIDFromHex(hexStr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*id = oid
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -104,7 +113,7 @@ func (id *ObjectId) DeepCopyInto(out *ObjectId) {
|
||||
*out = *id
|
||||
}
|
||||
|
||||
// DeepCopy copies the receiver into a new ObjectId.
|
||||
// DeepCopy copies the receiver into a new [ObjectId].
|
||||
func (id *ObjectId) DeepCopy() *ObjectId {
|
||||
if id == nil {
|
||||
return nil
|
||||
@@ -113,3 +122,18 @@ func (id *ObjectId) DeepCopy() *ObjectId {
|
||||
id.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// objectIDFromHex parses a 24-character hex string into an [ObjectId].
|
||||
func objectIDFromHex(s string) (ObjectId, error) {
|
||||
const objectIDHexLen = 24
|
||||
if len(s) != objectIDHexLen {
|
||||
return nilObjectID, fmt.Errorf("the provided hex string %q is not a valid ObjectID: %w", s, ErrFormat)
|
||||
}
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nilObjectID, fmt.Errorf("the provided hex string %q is not a valid ObjectID: %w", s, err)
|
||||
}
|
||||
var oid ObjectId
|
||||
copy(oid[:], b)
|
||||
return oid, nil
|
||||
}
|
||||
|
||||
+13
-14
@@ -10,35 +10,34 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
func init() { //nolint:gochecknoinits // registers date format in the default registry
|
||||
d := Date{}
|
||||
// register this format in the default registry
|
||||
Default.Add("date", &d, IsDate)
|
||||
}
|
||||
|
||||
// IsDate returns true when the string is a valid date
|
||||
// IsDate returns true when the string is a valid date.
|
||||
func IsDate(str string) bool {
|
||||
_, err := time.Parse(RFC3339FullDate, str)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
const (
|
||||
// RFC3339FullDate represents a full-date as specified by RFC3339
|
||||
// RFC3339FullDate represents a full-date as specified by RFC3339.
|
||||
// See: http://goo.gl/xXOvVd
|
||||
RFC3339FullDate = "2006-01-02"
|
||||
)
|
||||
|
||||
// Date represents a date from the API
|
||||
// Date represents a date from the API.
|
||||
//
|
||||
// swagger:strfmt date
|
||||
// swagger:strfmt date.
|
||||
type Date time.Time
|
||||
|
||||
// String converts this date into a string
|
||||
// String converts this date into a string.
|
||||
func (d Date) String() string {
|
||||
return time.Time(d).Format(RFC3339FullDate)
|
||||
}
|
||||
|
||||
// UnmarshalText parses a text representation into a date type
|
||||
// UnmarshalText parses a text representation into a date type.
|
||||
func (d *Date) UnmarshalText(text []byte) error {
|
||||
if len(text) == 0 {
|
||||
return nil
|
||||
@@ -51,7 +50,7 @@ func (d *Date) UnmarshalText(text []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalText serializes this date type to string
|
||||
// MarshalText serializes this date type to string.
|
||||
func (d Date) MarshalText() ([]byte, error) {
|
||||
return []byte(d.String()), nil
|
||||
}
|
||||
@@ -79,12 +78,12 @@ func (d Date) Value() (driver.Value, error) {
|
||||
return driver.Value(d.String()), nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the Date as JSON
|
||||
// MarshalJSON returns the Date as JSON.
|
||||
func (d Date) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(time.Time(d).Format(RFC3339FullDate))
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets the Date from JSON
|
||||
// UnmarshalJSON sets the Date from JSON.
|
||||
func (d *Date) UnmarshalJSON(data []byte) error {
|
||||
if string(data) == jsonNull {
|
||||
return nil
|
||||
@@ -126,12 +125,12 @@ func (d *Date) GobDecode(data []byte) error {
|
||||
return d.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface.
|
||||
func (d Date) MarshalBinary() ([]byte, error) {
|
||||
return time.Time(d).MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface.
|
||||
func (d *Date) UnmarshalBinary(data []byte) error {
|
||||
var original time.Time
|
||||
|
||||
@@ -145,7 +144,7 @@ func (d *Date) UnmarshalBinary(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Equal checks if two Date instances are equal
|
||||
// Equal checks if two Date instances are equal.
|
||||
func (d Date) Equal(d2 Date) bool {
|
||||
return time.Time(d).Equal(time.Time(d2))
|
||||
}
|
||||
|
||||
+221
-213
File diff suppressed because it is too large
Load Diff
+1
-3
@@ -1,7 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package strfmt contains custom string formats
|
||||
//
|
||||
// TODO: add info on how to define and register a custom format
|
||||
// Package strfmt contains custom string formats.
|
||||
package strfmt
|
||||
|
||||
+12
-12
@@ -14,9 +14,8 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
func init() { //nolint:gochecknoinits // registers duration format in the default registry
|
||||
d := Duration(0)
|
||||
// register this format in the default registry
|
||||
Default.Add("duration", &d, IsDuration)
|
||||
}
|
||||
|
||||
@@ -25,6 +24,7 @@ const (
|
||||
daysInWeek = 7
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // package-level lookup tables for duration parsing
|
||||
var (
|
||||
timeUnits = [][]string{
|
||||
{"ns", "nano"},
|
||||
@@ -51,7 +51,7 @@ var (
|
||||
durationMatcher = regexp.MustCompile(`^(((?:-\s?)?\d+)(\.\d+)?\s*([A-Za-zµ]+))`)
|
||||
)
|
||||
|
||||
// IsDuration returns true if the provided string is a valid duration
|
||||
// IsDuration returns true if the provided string is a valid duration.
|
||||
func IsDuration(str string) bool {
|
||||
_, err := ParseDuration(str)
|
||||
return err == nil
|
||||
@@ -60,17 +60,17 @@ func IsDuration(str string) bool {
|
||||
// Duration represents a duration
|
||||
//
|
||||
// Duration stores a period of time as a nanosecond count, with the largest
|
||||
// repesentable duration being approximately 290 years.
|
||||
// representable duration being approximately 290 years.
|
||||
//
|
||||
// swagger:strfmt duration
|
||||
// swagger:strfmt duration.
|
||||
type Duration time.Duration
|
||||
|
||||
// MarshalText turns this instance into text
|
||||
// MarshalText turns this instance into text.
|
||||
func (d Duration) MarshalText() ([]byte, error) {
|
||||
return []byte(time.Duration(d).String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText hydrates this instance from text
|
||||
// UnmarshalText hydrates this instance from text.
|
||||
func (d *Duration) UnmarshalText(data []byte) error { // validation is performed later on
|
||||
dd, err := ParseDuration(string(data))
|
||||
if err != nil {
|
||||
@@ -80,7 +80,7 @@ func (d *Duration) UnmarshalText(data []byte) error { // validation is performed
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseDuration parses a duration from a string, compatible with scala duration syntax
|
||||
// ParseDuration parses a duration from a string, compatible with scala duration syntax.
|
||||
func ParseDuration(cand string) (time.Duration, error) {
|
||||
if dur, err := time.ParseDuration(cand); err == nil {
|
||||
return dur, nil
|
||||
@@ -143,7 +143,7 @@ func ParseDuration(cand string) (time.Duration, error) {
|
||||
// Scan reads a Duration value from database driver type.
|
||||
func (d *Duration) Scan(raw any) error {
|
||||
switch v := raw.(type) {
|
||||
// TODO: case []byte: // ?
|
||||
// Proposal for enhancement: case []byte: // ?
|
||||
case int64:
|
||||
*d = Duration(v)
|
||||
case float64:
|
||||
@@ -162,17 +162,17 @@ func (d Duration) Value() (driver.Value, error) {
|
||||
return driver.Value(int64(d)), nil
|
||||
}
|
||||
|
||||
// String converts this duration to a string
|
||||
// String converts this duration to a string.
|
||||
func (d Duration) String() string {
|
||||
return time.Duration(d).String()
|
||||
}
|
||||
|
||||
// MarshalJSON returns the Duration as JSON
|
||||
// MarshalJSON returns the Duration as JSON.
|
||||
func (d Duration) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(time.Duration(d).String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets the Duration from JSON
|
||||
// UnmarshalJSON sets the Duration from JSON.
|
||||
func (d *Duration) UnmarshalJSON(data []byte) error {
|
||||
if string(data) == jsonNull {
|
||||
return nil
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ package strfmt
|
||||
|
||||
type strfmtError string
|
||||
|
||||
// ErrFormat is an error raised by the strfmt package
|
||||
// ErrFormat is an error raised by the [strfmt] package.
|
||||
const ErrFormat strfmtError = "format error"
|
||||
|
||||
func (e strfmtError) Error() string {
|
||||
|
||||
+89
-85
@@ -16,20 +16,20 @@ import (
|
||||
"github.com/go-viper/mapstructure/v2"
|
||||
)
|
||||
|
||||
// Default is the default formats registry
|
||||
var Default = NewSeededFormats(nil, nil)
|
||||
// Default is the default formats registry.
|
||||
var Default = NewSeededFormats(nil, nil) //nolint:gochecknoglobals // package-level default registry, by design
|
||||
|
||||
// Validator represents a validator for a string format.
|
||||
type Validator func(string) bool
|
||||
|
||||
// NewFormats creates a new formats registry seeded with the values from the default
|
||||
func NewFormats() Registry {
|
||||
// NewFormats creates a new formats registry seeded with the values from the default.
|
||||
func NewFormats() Registry { //nolint:ireturn // factory function returns the Registry interface by design
|
||||
//nolint:forcetypeassert
|
||||
return NewSeededFormats(Default.(*defaultFormats).data, nil)
|
||||
}
|
||||
|
||||
// NewSeededFormats creates a new formats registry
|
||||
func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry {
|
||||
// NewSeededFormats creates a new formats registry.
|
||||
func NewSeededFormats(seeds []knownFormat, normalizer NameNormalizer) Registry { //nolint:ireturn // factory function returns the Registry interface by design
|
||||
if normalizer == nil {
|
||||
normalizer = DefaultNameNormalizer
|
||||
}
|
||||
@@ -50,7 +50,7 @@ type knownFormat struct {
|
||||
// NameNormalizer is a function that normalizes a format name.
|
||||
type NameNormalizer func(string) string
|
||||
|
||||
// DefaultNameNormalizer removes all dashes
|
||||
// DefaultNameNormalizer removes all dashes.
|
||||
func DefaultNameNormalizer(name string) string {
|
||||
return strings.ReplaceAll(name, "-", "")
|
||||
}
|
||||
@@ -62,8 +62,8 @@ type defaultFormats struct {
|
||||
normalizeName NameNormalizer
|
||||
}
|
||||
|
||||
// MapStructureHookFunc is a decode hook function for mapstructure
|
||||
func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
|
||||
// MapStructureHookFunc is a decode hook function for mapstructure.
|
||||
func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc { //nolint:ireturn // returns interface required by mapstructure
|
||||
return func(from reflect.Type, to reflect.Type, obj any) (any, error) {
|
||||
if from.Kind() != reflect.String {
|
||||
return obj, nil
|
||||
@@ -76,83 +76,87 @@ func (f *defaultFormats) MapStructureHookFunc() mapstructure.DecodeHookFunc {
|
||||
for _, v := range f.data {
|
||||
tpe, _ := f.GetType(v.Name)
|
||||
if to == tpe {
|
||||
switch v.Name {
|
||||
case "date":
|
||||
d, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Date(d), nil
|
||||
case "datetime":
|
||||
input := data
|
||||
if len(input) == 0 {
|
||||
return nil, fmt.Errorf("empty string is an invalid datetime format: %w", ErrFormat)
|
||||
}
|
||||
return ParseDateTime(input)
|
||||
case "duration":
|
||||
dur, err := ParseDuration(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Duration(dur), nil
|
||||
case "uri":
|
||||
return URI(data), nil
|
||||
case "email":
|
||||
return Email(data), nil
|
||||
case "uuid":
|
||||
return UUID(data), nil
|
||||
case "uuid3":
|
||||
return UUID3(data), nil
|
||||
case "uuid4":
|
||||
return UUID4(data), nil
|
||||
case "uuid5":
|
||||
return UUID5(data), nil
|
||||
case "uuid7":
|
||||
return UUID7(data), nil
|
||||
case "hostname":
|
||||
return Hostname(data), nil
|
||||
case "ipv4":
|
||||
return IPv4(data), nil
|
||||
case "ipv6":
|
||||
return IPv6(data), nil
|
||||
case "cidr":
|
||||
return CIDR(data), nil
|
||||
case "mac":
|
||||
return MAC(data), nil
|
||||
case "isbn":
|
||||
return ISBN(data), nil
|
||||
case "isbn10":
|
||||
return ISBN10(data), nil
|
||||
case "isbn13":
|
||||
return ISBN13(data), nil
|
||||
case "creditcard":
|
||||
return CreditCard(data), nil
|
||||
case "ssn":
|
||||
return SSN(data), nil
|
||||
case "hexcolor":
|
||||
return HexColor(data), nil
|
||||
case "rgbcolor":
|
||||
return RGBColor(data), nil
|
||||
case "byte":
|
||||
return Base64(data), nil
|
||||
case "password":
|
||||
return Password(data), nil
|
||||
case "ulid":
|
||||
ulid, err := ParseULID(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ulid, nil
|
||||
default:
|
||||
return nil, errors.InvalidTypeName(v.Name)
|
||||
}
|
||||
return decodeFormatFromString(v.Name, data)
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a new format, return true if this was a new item instead of a replacement
|
||||
// decodeFormatFromString decodes a string into the appropriate format type by name.
|
||||
func decodeFormatFromString(name, data string) (any, error) { //nolint:gocyclo,cyclop // flat switch over format names, no real complexity
|
||||
switch name {
|
||||
case "date":
|
||||
d, err := time.ParseInLocation(RFC3339FullDate, data, DefaultTimeLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Date(d), nil
|
||||
case "datetime":
|
||||
if len(data) == 0 {
|
||||
return nil, fmt.Errorf("empty string is an invalid datetime format: %w", ErrFormat)
|
||||
}
|
||||
return ParseDateTime(data)
|
||||
case "duration":
|
||||
dur, err := ParseDuration(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return Duration(dur), nil
|
||||
case "uri":
|
||||
return URI(data), nil
|
||||
case "email":
|
||||
return Email(data), nil
|
||||
case "uuid":
|
||||
return UUID(data), nil
|
||||
case "uuid3":
|
||||
return UUID3(data), nil
|
||||
case "uuid4":
|
||||
return UUID4(data), nil
|
||||
case "uuid5":
|
||||
return UUID5(data), nil
|
||||
case "uuid7":
|
||||
return UUID7(data), nil
|
||||
case "hostname":
|
||||
return Hostname(data), nil
|
||||
case "ipv4":
|
||||
return IPv4(data), nil
|
||||
case "ipv6":
|
||||
return IPv6(data), nil
|
||||
case "cidr":
|
||||
return CIDR(data), nil
|
||||
case "mac":
|
||||
return MAC(data), nil
|
||||
case "isbn":
|
||||
return ISBN(data), nil
|
||||
case "isbn10":
|
||||
return ISBN10(data), nil
|
||||
case "isbn13":
|
||||
return ISBN13(data), nil
|
||||
case "creditcard":
|
||||
return CreditCard(data), nil
|
||||
case "ssn":
|
||||
return SSN(data), nil
|
||||
case "hexcolor":
|
||||
return HexColor(data), nil
|
||||
case "rgbcolor":
|
||||
return RGBColor(data), nil
|
||||
case "byte":
|
||||
return Base64(data), nil
|
||||
case "password":
|
||||
return Password(data), nil
|
||||
case "ulid":
|
||||
ulid, err := ParseULID(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ulid, nil
|
||||
default:
|
||||
return nil, errors.InvalidTypeName(name)
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a new format, return true if this was a new item instead of a replacement.
|
||||
func (f *defaultFormats) Add(name string, strfmt Format, validator Validator) bool {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
@@ -178,7 +182,7 @@ func (f *defaultFormats) Add(name string, strfmt Format, validator Validator) bo
|
||||
return true
|
||||
}
|
||||
|
||||
// GetType gets the type for the specified name
|
||||
// GetType gets the type for the specified name.
|
||||
func (f *defaultFormats) GetType(name string) (reflect.Type, bool) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
@@ -191,7 +195,7 @@ func (f *defaultFormats) GetType(name string) (reflect.Type, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// DelByName removes the format by the specified name, returns true when an item was actually removed
|
||||
// DelByName removes the format by the specified name, returns true when an item was actually removed.
|
||||
func (f *defaultFormats) DelByName(name string) bool {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
@@ -208,7 +212,7 @@ func (f *defaultFormats) DelByName(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// DelByFormat removes the specified format, returns true when an item was actually removed
|
||||
// DelByFormat removes the specified format, returns true when an item was actually removed.
|
||||
func (f *defaultFormats) DelByFormat(strfmt Format) bool {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
@@ -228,7 +232,7 @@ func (f *defaultFormats) DelByFormat(strfmt Format) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsName returns true if this registry contains the specified name
|
||||
// ContainsName returns true if this registry contains the specified name.
|
||||
func (f *defaultFormats) ContainsName(name string) bool {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
@@ -241,7 +245,7 @@ func (f *defaultFormats) ContainsName(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ContainsFormat returns true if this registry contains the specified format
|
||||
// ContainsFormat returns true if this registry contains the specified format.
|
||||
func (f *defaultFormats) ContainsFormat(strfmt Format) bool {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
use (
|
||||
.
|
||||
./enable/mongodb
|
||||
./internal/testintegration
|
||||
)
|
||||
|
||||
go 1.24.0
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
+7
-7
@@ -13,7 +13,7 @@ import (
|
||||
// Format represents a string format.
|
||||
//
|
||||
// All implementations of Format provide a string representation and text
|
||||
// marshaling/unmarshaling interface to be used by encoders (e.g. encoding/json).
|
||||
// marshaling/unmarshaling interface to be used by encoders (e.g. encoding/[json]).
|
||||
type Format interface {
|
||||
String() string
|
||||
encoding.TextMarshaler
|
||||
@@ -22,11 +22,11 @@ type Format interface {
|
||||
|
||||
// Registry is a registry of string formats, with a validation method.
|
||||
type Registry interface {
|
||||
Add(string, Format, Validator) bool
|
||||
DelByName(string) bool
|
||||
GetType(string) (reflect.Type, bool)
|
||||
ContainsName(string) bool
|
||||
Validates(string, string) bool
|
||||
Parse(string, string) (any, error)
|
||||
Add(name string, strfmt Format, validator Validator) bool
|
||||
DelByName(name string) bool
|
||||
GetType(name string) (reflect.Type, bool)
|
||||
ContainsName(name string) bool
|
||||
Validates(name, data string) bool
|
||||
Parse(name, data string) (any, error)
|
||||
MapStructureHookFunc() mapstructure.DecodeHookFunc
|
||||
}
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package bsonlite provides a minimal BSON codec for strfmt types.
|
||||
//
|
||||
// This codec produces BSON output compatible with go.mongodb.org/mongo-driver/v2
|
||||
// (v2.5.0). It handles only the exact BSON patterns used by strfmt:
|
||||
// single-key {"data": value} documents with string, DateTime, or ObjectID values.
|
||||
//
|
||||
// This package is intended to provide a backward-compatible API to users of
|
||||
// go-openapi/strfmt. It is not intended to be maintained or to follow the
|
||||
// evolutions of the official MongoDB drivers. For up-to-date MongoDB support,
|
||||
// import "github.com/go-openapi/strfmt/enable/mongodb" to replace this codec
|
||||
// with one backed by the real driver.
|
||||
package bsonlite
|
||||
|
||||
import "time"
|
||||
|
||||
// Codec provides BSON document marshal/unmarshal for strfmt types.
|
||||
//
|
||||
// MarshalDoc encodes a single-key BSON document {"data": value}.
|
||||
// The value must be one of: string, time.Time, or [12]byte (ObjectID).
|
||||
//
|
||||
// UnmarshalDoc decodes a BSON document and returns the "data" field's value.
|
||||
// Returns one of: string, time.Time, or [12]byte depending on the BSON type.
|
||||
type Codec interface {
|
||||
MarshalDoc(value any) ([]byte, error)
|
||||
UnmarshalDoc(data []byte) (any, error)
|
||||
}
|
||||
|
||||
// C is the active BSON codec.
|
||||
//
|
||||
//nolint:gochecknoglobals // replaceable codec, by design
|
||||
var C Codec = liteCodec{}
|
||||
|
||||
// Replace swaps the active BSON codec with the provided implementation.
|
||||
// This is intended to be called from enable/mongodb's init().
|
||||
//
|
||||
// Since [Replace] affects the global state of the package, it is not intended for concurrent use.
|
||||
func Replace(c Codec) {
|
||||
C = c
|
||||
}
|
||||
|
||||
// BSON type tags (from the BSON specification).
|
||||
const (
|
||||
TypeString byte = 0x02
|
||||
TypeObjectID byte = 0x07
|
||||
TypeDateTime byte = 0x09
|
||||
TypeNull byte = 0x0A
|
||||
)
|
||||
|
||||
// ObjectIDSize is the size of a BSON ObjectID in bytes.
|
||||
const ObjectIDSize = 12
|
||||
|
||||
// DateTimeToMillis converts a time.Time to BSON DateTime milliseconds.
|
||||
func DateTimeToMillis(t time.Time) int64 {
|
||||
const (
|
||||
millisec = 1000
|
||||
microsec = 1_000_000
|
||||
)
|
||||
return t.Unix()*millisec + int64(t.Nanosecond())/microsec
|
||||
}
|
||||
|
||||
// MillisToTime converts BSON DateTime milliseconds to time.Time.
|
||||
func MillisToTime(millis int64) time.Time {
|
||||
const (
|
||||
millisec = 1000
|
||||
nanosPerMs = 1_000_000
|
||||
)
|
||||
return time.Unix(millis/millisec, millis%millisec*nanosPerMs)
|
||||
}
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2015-2025 go-swagger maintainers
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package bsonlite
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// liteCodec is a minimal BSON codec that handles only the patterns used by strfmt:
|
||||
// single-key documents of the form {"data": <value>} where value is a string,
|
||||
// BSON DateTime (time.Time), or BSON ObjectID ([12]byte).
|
||||
type liteCodec struct{}
|
||||
|
||||
var _ Codec = liteCodec{}
|
||||
|
||||
func (liteCodec) MarshalDoc(value any) ([]byte, error) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return marshalStringDoc(v), nil
|
||||
case time.Time:
|
||||
return marshalDateTimeDoc(v), nil
|
||||
case [ObjectIDSize]byte:
|
||||
return marshalObjectIDDoc(v), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("bsonlite: unsupported value type %T: %w", value, errUnsupportedType)
|
||||
}
|
||||
}
|
||||
|
||||
func (liteCodec) UnmarshalDoc(data []byte) (any, error) {
|
||||
return unmarshalDoc(data)
|
||||
}
|
||||
|
||||
// BSON wire format helpers.
|
||||
//
|
||||
// Document: int32(size) + elements + 0x00
|
||||
// Element: byte(type) + cstring(key) + value
|
||||
// String: int32(len+1) + bytes + 0x00
|
||||
// DateTime: int64 (LE, millis since epoch)
|
||||
// ObjectID: [12]byte
|
||||
|
||||
const dataKey = "data\x00"
|
||||
|
||||
func marshalStringDoc(s string) []byte {
|
||||
sBytes := []byte(s)
|
||||
// doc_size(4) + type(1) + key("data\0"=5) + strlen(4) + string + \0(1) + doc_term(1)
|
||||
docSize := 4 + 1 + len(dataKey) + 4 + len(sBytes) + 1 + 1
|
||||
|
||||
buf := make([]byte, docSize)
|
||||
pos := 0
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[pos:], uint32(docSize)) //nolint:gosec // size is computed from input, cannot overflow
|
||||
pos += 4
|
||||
|
||||
buf[pos] = TypeString
|
||||
pos++
|
||||
|
||||
pos += copy(buf[pos:], dataKey)
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[pos:], uint32(len(sBytes)+1)) //nolint:gosec // string length cannot overflow uint32
|
||||
pos += 4
|
||||
|
||||
pos += copy(buf[pos:], sBytes)
|
||||
buf[pos] = 0 // string null terminator
|
||||
pos++
|
||||
|
||||
buf[pos] = 0 // document terminator
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
func marshalDateTimeDoc(t time.Time) []byte {
|
||||
// doc_size(4) + type(1) + key("data\0"=5) + int64(8) + doc_term(1)
|
||||
const docSize = 4 + 1 + 5 + 8 + 1
|
||||
|
||||
buf := make([]byte, docSize)
|
||||
pos := 0
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[pos:], docSize)
|
||||
pos += 4
|
||||
|
||||
buf[pos] = TypeDateTime
|
||||
pos++
|
||||
|
||||
pos += copy(buf[pos:], dataKey)
|
||||
|
||||
millis := DateTimeToMillis(t)
|
||||
binary.LittleEndian.PutUint64(buf[pos:], uint64(millis)) //nolint:gosec // negative datetime millis are valid
|
||||
// pos += 8
|
||||
|
||||
buf[docSize-1] = 0 // document terminator
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
func marshalObjectIDDoc(oid [ObjectIDSize]byte) []byte {
|
||||
// doc_size(4) + type(1) + key("data\0"=5) + objectid(12) + doc_term(1)
|
||||
const docSize = 4 + 1 + 5 + ObjectIDSize + 1
|
||||
|
||||
buf := make([]byte, docSize)
|
||||
pos := 0
|
||||
|
||||
binary.LittleEndian.PutUint32(buf[pos:], docSize)
|
||||
pos += 4
|
||||
|
||||
buf[pos] = TypeObjectID
|
||||
pos++
|
||||
|
||||
pos += copy(buf[pos:], dataKey)
|
||||
|
||||
copy(buf[pos:], oid[:])
|
||||
// pos += ObjectIDSize
|
||||
|
||||
buf[docSize-1] = 0 // document terminator
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
var (
|
||||
errUnsupportedType = errors.New("bsonlite: unsupported type")
|
||||
errDocTooShort = errors.New("bsonlite: document too short")
|
||||
errDocSize = errors.New("bsonlite: document size mismatch")
|
||||
errNoTerminator = errors.New("bsonlite: missing key terminator")
|
||||
errTruncated = errors.New("bsonlite: truncated value")
|
||||
errDataNotFound = errors.New("bsonlite: \"data\" field not found")
|
||||
)
|
||||
|
||||
func unmarshalDoc(raw []byte) (any, error) {
|
||||
const minDocSize = 5 // int32(size) + terminator
|
||||
|
||||
if len(raw) < minDocSize {
|
||||
return nil, errDocTooShort
|
||||
}
|
||||
|
||||
docSize := int(binary.LittleEndian.Uint32(raw[:4]))
|
||||
if docSize != len(raw) {
|
||||
return nil, errDocSize
|
||||
}
|
||||
|
||||
pos := 4
|
||||
|
||||
for pos < docSize-1 {
|
||||
if pos >= len(raw) {
|
||||
return nil, errTruncated
|
||||
}
|
||||
typeByte := raw[pos]
|
||||
pos++
|
||||
|
||||
// Read key (cstring: bytes until 0x00).
|
||||
keyStart := pos
|
||||
for pos < len(raw) && raw[pos] != 0 {
|
||||
pos++
|
||||
}
|
||||
if pos >= len(raw) {
|
||||
return nil, errNoTerminator
|
||||
}
|
||||
key := string(raw[keyStart:pos])
|
||||
pos++ // skip null terminator
|
||||
|
||||
val, newPos, err := readValue(typeByte, raw, pos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pos = newPos
|
||||
|
||||
if key == "data" {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errDataNotFound
|
||||
}
|
||||
|
||||
func readValue(typeByte byte, raw []byte, pos int) (any, int, error) {
|
||||
switch typeByte {
|
||||
case TypeString:
|
||||
if pos+4 > len(raw) {
|
||||
return nil, 0, errTruncated
|
||||
}
|
||||
strLen := int(binary.LittleEndian.Uint32(raw[pos:]))
|
||||
pos += 4
|
||||
if pos+strLen > len(raw) || strLen < 1 {
|
||||
return nil, 0, errTruncated
|
||||
}
|
||||
s := string(raw[pos : pos+strLen-1]) // exclude null terminator
|
||||
return s, pos + strLen, nil
|
||||
|
||||
case TypeObjectID:
|
||||
if pos+ObjectIDSize > len(raw) {
|
||||
return nil, 0, errTruncated
|
||||
}
|
||||
var oid [ObjectIDSize]byte
|
||||
copy(oid[:], raw[pos:pos+ObjectIDSize])
|
||||
return oid, pos + ObjectIDSize, nil
|
||||
|
||||
case TypeDateTime:
|
||||
const dateTimeSize = 8
|
||||
if pos+dateTimeSize > len(raw) {
|
||||
return nil, 0, errTruncated
|
||||
}
|
||||
millis := int64(binary.LittleEndian.Uint64(raw[pos:])) //nolint:gosec // negative datetime millis are valid
|
||||
return MillisToTime(millis), pos + dateTimeSize, nil
|
||||
|
||||
case TypeNull:
|
||||
return nil, pos, nil
|
||||
|
||||
default:
|
||||
return nil, 0, fmt.Errorf("bsonlite: unsupported BSON type 0x%02x: %w", typeByte, errUnsupportedType)
|
||||
}
|
||||
}
|
||||
+521
-566
File diff suppressed because it is too large
Load Diff
+45
-37
@@ -12,14 +12,12 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// UnixZero sets the zero unix UTC timestamp we want to compare against.
|
||||
//
|
||||
// Unix 0 for an EST timezone is not equivalent to a UTC timezone.
|
||||
UnixZero = time.Unix(0, 0).UTC()
|
||||
)
|
||||
// UnixZero sets the zero unix UTC timestamp we want to compare against.
|
||||
//
|
||||
// Unix 0 for an EST timezone is not equivalent to a UTC timezone.
|
||||
var UnixZero = time.Unix(0, 0).UTC() //nolint:gochecknoglobals // package-level sentinel value for unix epoch
|
||||
|
||||
func init() {
|
||||
func init() { //nolint:gochecknoinits // registers datetime format in the default registry
|
||||
dt := DateTime{}
|
||||
Default.Add("datetime", &dt, IsDateTime)
|
||||
}
|
||||
@@ -50,38 +48,48 @@ func IsDateTime(str string) bool {
|
||||
}
|
||||
|
||||
const (
|
||||
// RFC3339Millis represents a ISO8601 format to millis instead of to nanos
|
||||
// RFC3339Millis represents a ISO8601 format to millis instead of to nanos.
|
||||
RFC3339Millis = "2006-01-02T15:04:05.000Z07:00"
|
||||
// RFC3339MillisNoColon represents a ISO8601 format to millis instead of to nanos
|
||||
// RFC3339MillisNoColon represents a ISO8601 format to millis instead of to nanos.
|
||||
RFC3339MillisNoColon = "2006-01-02T15:04:05.000Z0700"
|
||||
// RFC3339Micro represents a ISO8601 format to micro instead of to nano
|
||||
// RFC3339Micro represents a ISO8601 format to micro instead of to nano.
|
||||
RFC3339Micro = "2006-01-02T15:04:05.000000Z07:00"
|
||||
// RFC3339MicroNoColon represents a ISO8601 format to micro instead of to nano
|
||||
// RFC3339MicroNoColon represents a ISO8601 format to micro instead of to nano.
|
||||
RFC3339MicroNoColon = "2006-01-02T15:04:05.000000Z0700"
|
||||
// ISO8601LocalTime represents a ISO8601 format to ISO8601 in local time (no timezone)
|
||||
// ISO8601LocalTime represents a ISO8601 format to ISO8601 in local time (no timezone).
|
||||
ISO8601LocalTime = "2006-01-02T15:04:05"
|
||||
// ISO8601TimeWithReducedPrecision represents a ISO8601 format with reduced precision (dropped secs)
|
||||
// ISO8601TimeWithReducedPrecision represents a ISO8601 format with reduced precision (dropped secs).
|
||||
ISO8601TimeWithReducedPrecision = "2006-01-02T15:04Z"
|
||||
// ISO8601TimeWithReducedPrecisionLocaltime represents a ISO8601 format with reduced precision and no timezone (dropped seconds + no timezone)
|
||||
// ISO8601TimeWithReducedPrecisionLocaltime represents a ISO8601 format with reduced precision and no timezone (dropped seconds + no timezone).
|
||||
ISO8601TimeWithReducedPrecisionLocaltime = "2006-01-02T15:04"
|
||||
// ISO8601TimeUniversalSortableDateTimePattern represents a ISO8601 universal sortable date time pattern.
|
||||
ISO8601TimeUniversalSortableDateTimePattern = "2006-01-02 15:04:05"
|
||||
// ISO8601TimeUniversalSortableDateTimePatternShortForm is the short form of ISO8601TimeUniversalSortableDateTimePattern
|
||||
// ISO8601TimeUniversalSortableDateTimePatternShortForm is the short form of [ISO8601TimeUniversalSortableDateTimePattern].
|
||||
ISO8601TimeUniversalSortableDateTimePatternShortForm = "2006-01-02"
|
||||
// DateTimePattern pattern to match for the date-time format from http://tools.ietf.org/html/rfc3339#section-5.6
|
||||
DateTimePattern = `^([0-9]{2}):([0-9]{2}):([0-9]{2})(.[0-9]+)?(z|([+-][0-9]{2}:[0-9]{2}))$`
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals // package-level configuration for datetime parsing and marshaling
|
||||
var (
|
||||
rxDateTime = regexp.MustCompile(DateTimePattern)
|
||||
|
||||
// DateTimeFormats is the collection of formats used by ParseDateTime()
|
||||
DateTimeFormats = []string{RFC3339Micro, RFC3339MicroNoColon, RFC3339Millis, RFC3339MillisNoColon, time.RFC3339, time.RFC3339Nano, ISO8601LocalTime, ISO8601TimeWithReducedPrecision, ISO8601TimeWithReducedPrecisionLocaltime, ISO8601TimeUniversalSortableDateTimePattern, ISO8601TimeUniversalSortableDateTimePatternShortForm}
|
||||
// DateTimeFormats is the collection of formats used by [ParseDateTime]().
|
||||
DateTimeFormats = []string{
|
||||
RFC3339Micro, RFC3339MicroNoColon,
|
||||
RFC3339Millis, RFC3339MillisNoColon,
|
||||
time.RFC3339, time.RFC3339Nano,
|
||||
ISO8601LocalTime,
|
||||
ISO8601TimeWithReducedPrecision,
|
||||
ISO8601TimeWithReducedPrecisionLocaltime,
|
||||
ISO8601TimeUniversalSortableDateTimePattern,
|
||||
ISO8601TimeUniversalSortableDateTimePatternShortForm,
|
||||
}
|
||||
|
||||
// MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds)
|
||||
// MarshalFormat sets the time resolution format used for marshaling time (set to milliseconds).
|
||||
MarshalFormat = RFC3339Millis
|
||||
|
||||
// NormalizeTimeForMarshal provides a normalization function on time before marshalling (e.g. time.UTC).
|
||||
// NormalizeTimeForMarshal provides a normalization function on time before marshaling (e.g. [time.UTC]).
|
||||
// By default, the time value is not changed.
|
||||
NormalizeTimeForMarshal = func(t time.Time) time.Time { return t }
|
||||
|
||||
@@ -89,7 +97,7 @@ var (
|
||||
DefaultTimeLocation = time.UTC
|
||||
)
|
||||
|
||||
// ParseDateTime parses a string that represents an ISO8601 time or a unix epoch
|
||||
// ParseDateTime parses a string that represents an ISO8601 time or a unix epoch.
|
||||
func ParseDateTime(data string) (DateTime, error) {
|
||||
if data == "" {
|
||||
return NewDateTime(), nil
|
||||
@@ -112,46 +120,46 @@ func ParseDateTime(data string) (DateTime, error) {
|
||||
// Most APIs we encounter want either millisecond or second precision times.
|
||||
// This just tries to make it worry-free.
|
||||
//
|
||||
// swagger:strfmt date-time
|
||||
// swagger:strfmt date-time.
|
||||
type DateTime time.Time
|
||||
|
||||
// NewDateTime is a representation of the UNIX epoch (January 1, 1970 00:00:00 UTC) for the [DateTime] type.
|
||||
//
|
||||
// Notice that this is not the zero value of the [DateTime] type.
|
||||
//
|
||||
// You may use [DateTime.IsUNIXZero] to check against this value.
|
||||
// You may use [DateTime.IsUnixZero] to check against this value.
|
||||
func NewDateTime() DateTime {
|
||||
return DateTime(time.Unix(0, 0).UTC())
|
||||
}
|
||||
|
||||
// MakeDateTime is a representation of the zero value of the [DateTime] type (January 1, year 1, 00:00:00 UTC).
|
||||
//
|
||||
// You may use [Datetime.IsZero] to check against this value.
|
||||
// You may use [DateTime.IsZero] to check against this value.
|
||||
func MakeDateTime() DateTime {
|
||||
return DateTime(time.Time{})
|
||||
}
|
||||
|
||||
// String converts this time to a string
|
||||
// String converts this time to a string.
|
||||
func (t DateTime) String() string {
|
||||
return NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat)
|
||||
}
|
||||
|
||||
// IsZero returns whether the date time is a zero value
|
||||
// IsZero returns whether the date time is a zero value.
|
||||
func (t DateTime) IsZero() bool {
|
||||
return time.Time(t).IsZero()
|
||||
}
|
||||
|
||||
// IsUnixZero returns whether the date time is equivalent to time.Unix(0, 0).UTC().
|
||||
// IsUnixZero returns whether the date time is equivalent to [time.Unix](0, 0).UTC().
|
||||
func (t DateTime) IsUnixZero() bool {
|
||||
return time.Time(t).Equal(UnixZero)
|
||||
}
|
||||
|
||||
// MarshalText implements the text marshaller interface
|
||||
// MarshalText implements the text marshaler interface.
|
||||
func (t DateTime) MarshalText() ([]byte, error) {
|
||||
return []byte(t.String()), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements the text unmarshaller interface
|
||||
// UnmarshalText implements the text unmarshaler interface.
|
||||
func (t *DateTime) UnmarshalText(text []byte) error {
|
||||
tt, err := ParseDateTime(string(text))
|
||||
if err != nil {
|
||||
@@ -161,9 +169,9 @@ func (t *DateTime) UnmarshalText(text []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Scan scans a DateTime value from database driver type.
|
||||
// Scan scans a [DateTime] value from database driver type.
|
||||
func (t *DateTime) Scan(raw any) error {
|
||||
// TODO: case int64: and case float64: ?
|
||||
// Proposal for enhancement: case int64: and case float64: ?
|
||||
switch v := raw.(type) {
|
||||
case []byte:
|
||||
return t.UnmarshalText(v)
|
||||
@@ -180,17 +188,17 @@ func (t *DateTime) Scan(raw any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value converts DateTime to a primitive value ready to written to a database.
|
||||
// Value converts [DateTime] to a primitive value ready to written to a database.
|
||||
func (t DateTime) Value() (driver.Value, error) {
|
||||
return driver.Value(t.String()), nil
|
||||
}
|
||||
|
||||
// MarshalJSON returns the DateTime as JSON
|
||||
// MarshalJSON returns the [DateTime] as JSON.
|
||||
func (t DateTime) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(NormalizeTimeForMarshal(time.Time(t)).Format(MarshalFormat))
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets the DateTime from JSON
|
||||
// UnmarshalJSON sets the [DateTime] from JSON.
|
||||
func (t *DateTime) UnmarshalJSON(data []byte) error {
|
||||
if string(data) == jsonNull {
|
||||
return nil
|
||||
@@ -213,7 +221,7 @@ func (t *DateTime) DeepCopyInto(out *DateTime) {
|
||||
*out = *t
|
||||
}
|
||||
|
||||
// DeepCopy copies the receiver into a new DateTime.
|
||||
// DeepCopy copies the receiver into a new [DateTime].
|
||||
func (t *DateTime) DeepCopy() *DateTime {
|
||||
if t == nil {
|
||||
return nil
|
||||
@@ -233,12 +241,12 @@ func (t *DateTime) GobDecode(data []byte) error {
|
||||
return t.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface.
|
||||
func (t DateTime) MarshalBinary() ([]byte, error) {
|
||||
return NormalizeTimeForMarshal(time.Time(t)).MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface.
|
||||
func (t *DateTime) UnmarshalBinary(data []byte) error {
|
||||
var original time.Time
|
||||
|
||||
@@ -252,7 +260,7 @@ func (t *DateTime) UnmarshalBinary(data []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Equal checks if two DateTime instances are equal using time.Time's Equal method
|
||||
// Equal checks if two [DateTime] instances are equal using [time.Time]'s Equal method.
|
||||
func (t DateTime) Equal(t2 DateTime) bool {
|
||||
return time.Time(t).Equal(time.Time(t2))
|
||||
}
|
||||
|
||||
+29
-27
@@ -11,23 +11,25 @@ import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/oklog/ulid"
|
||||
"github.com/oklog/ulid/v2"
|
||||
)
|
||||
|
||||
// ULID represents a ulid string format
|
||||
// ref:
|
||||
// ULID represents a [ulid] string format.
|
||||
//
|
||||
// # Reference
|
||||
//
|
||||
// https://github.com/ulid/spec
|
||||
//
|
||||
// impl:
|
||||
// # Implementation
|
||||
//
|
||||
// https://github.com/oklog/ulid
|
||||
//
|
||||
// swagger:strfmt ulid
|
||||
// swagger:strfmt ulid.
|
||||
type ULID struct {
|
||||
ulid.ULID
|
||||
}
|
||||
|
||||
//nolint:gochecknoglobals // package-level ULID configuration and overridable scan/value functions
|
||||
var (
|
||||
ulidEntropyPool = sync.Pool{
|
||||
New: func() any {
|
||||
@@ -35,6 +37,7 @@ var (
|
||||
},
|
||||
}
|
||||
|
||||
// ULIDScanDefaultFunc is the default implementation for scanning a [ULID] from a database driver value.
|
||||
ULIDScanDefaultFunc = func(raw any) (ULID, error) {
|
||||
u := NewULIDZero()
|
||||
switch x := raw.(type) {
|
||||
@@ -54,45 +57,44 @@ var (
|
||||
return u, fmt.Errorf("cannot sql.Scan() strfmt.ULID from: %#v: %w", raw, ulid.ErrScanValue)
|
||||
}
|
||||
|
||||
// ULIDScanOverrideFunc allows you to override the Scan method of the ULID type
|
||||
// ULIDScanOverrideFunc allows you to override the Scan method of the [ULID] type.
|
||||
ULIDScanOverrideFunc = ULIDScanDefaultFunc
|
||||
|
||||
// ULIDValueDefaultFunc is the default implementation for converting a [ULID] to a database driver value.
|
||||
ULIDValueDefaultFunc = func(u ULID) (driver.Value, error) {
|
||||
return driver.Value(u.String()), nil
|
||||
}
|
||||
|
||||
// ULIDValueOverrideFunc allows you to override the Value method of the ULID type
|
||||
// ULIDValueOverrideFunc allows you to override the Value method of the [ULID] type.
|
||||
ULIDValueOverrideFunc = ULIDValueDefaultFunc
|
||||
)
|
||||
|
||||
func init() {
|
||||
// register formats in the default registry:
|
||||
// - ulid
|
||||
func init() { //nolint:gochecknoinits // registers ulid format in the default registry
|
||||
ulid := ULID{}
|
||||
Default.Add("ulid", &ulid, IsULID)
|
||||
}
|
||||
|
||||
// IsULID checks if provided string is ULID format
|
||||
// Be noticed that this function considers overflowed ULID as non-ulid.
|
||||
// For more details see https://github.com/ulid/spec
|
||||
// IsULID checks if provided string is [ULID] format
|
||||
// Be noticed that this function considers overflowed [ULID] as non-[ulid].
|
||||
// For more details see https://github.com/[ulid]/spec
|
||||
func IsULID(str string) bool {
|
||||
_, err := ulid.ParseStrict(str)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// ParseULID parses a string that represents an valid ULID
|
||||
// ParseULID parses a string that represents an valid [ULID].
|
||||
func ParseULID(str string) (ULID, error) {
|
||||
var u ULID
|
||||
|
||||
return u, u.UnmarshalText([]byte(str))
|
||||
}
|
||||
|
||||
// NewULIDZero returns a zero valued ULID type
|
||||
// NewULIDZero returns a zero valued [ULID] type.
|
||||
func NewULIDZero() ULID {
|
||||
return ULID{}
|
||||
}
|
||||
|
||||
// NewULID generates new unique ULID value and a error if any
|
||||
// NewULID generates new unique [ULID] value and a error if any.
|
||||
func NewULID() (ULID, error) {
|
||||
var u ULID
|
||||
|
||||
@@ -112,22 +114,22 @@ func NewULID() (ULID, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// GetULID returns underlying instance of ULID
|
||||
// GetULID returns underlying instance of [ULID].
|
||||
func (u *ULID) GetULID() any {
|
||||
return u.ULID
|
||||
}
|
||||
|
||||
// MarshalText returns this instance into text
|
||||
// MarshalText returns this instance into text.
|
||||
func (u ULID) MarshalText() ([]byte, error) {
|
||||
return u.ULID.MarshalText()
|
||||
}
|
||||
|
||||
// UnmarshalText hydrates this instance from text
|
||||
// UnmarshalText hydrates this instance from text.
|
||||
func (u *ULID) UnmarshalText(data []byte) error { // validation is performed later on
|
||||
return u.ULID.UnmarshalText(data)
|
||||
}
|
||||
|
||||
// Scan reads a value from a database driver
|
||||
// Scan reads a value from a database driver.
|
||||
func (u *ULID) Scan(raw any) error {
|
||||
ul, err := ULIDScanOverrideFunc(raw)
|
||||
if err == nil {
|
||||
@@ -136,7 +138,7 @@ func (u *ULID) Scan(raw any) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Value converts a value to a database driver value
|
||||
// Value converts a value to a database driver value.
|
||||
func (u ULID) Value() (driver.Value, error) {
|
||||
return ULIDValueOverrideFunc(u)
|
||||
}
|
||||
@@ -145,12 +147,12 @@ func (u ULID) String() string {
|
||||
return u.ULID.String()
|
||||
}
|
||||
|
||||
// MarshalJSON returns the ULID as JSON
|
||||
// MarshalJSON returns the [ULID] as JSON.
|
||||
func (u ULID) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(u.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON sets the ULID from JSON
|
||||
// UnmarshalJSON sets the [ULID] from JSON.
|
||||
func (u *ULID) UnmarshalJSON(data []byte) error {
|
||||
if string(data) == jsonNull {
|
||||
return nil
|
||||
@@ -172,7 +174,7 @@ func (u *ULID) DeepCopyInto(out *ULID) {
|
||||
*out = *u
|
||||
}
|
||||
|
||||
// DeepCopy copies the receiver into a new ULID.
|
||||
// DeepCopy copies the receiver into a new [ULID].
|
||||
func (u *ULID) DeepCopy() *ULID {
|
||||
if u == nil {
|
||||
return nil
|
||||
@@ -192,17 +194,17 @@ func (u *ULID) GobDecode(data []byte) error {
|
||||
return u.ULID.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// MarshalBinary implements the encoding.BinaryMarshaler interface.
|
||||
// MarshalBinary implements the encoding.[encoding.BinaryMarshaler] interface.
|
||||
func (u ULID) MarshalBinary() ([]byte, error) {
|
||||
return u.ULID.MarshalBinary()
|
||||
}
|
||||
|
||||
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
|
||||
// UnmarshalBinary implements the encoding.[encoding.BinaryUnmarshaler] interface.
|
||||
func (u *ULID) UnmarshalBinary(data []byte) error {
|
||||
return u.ULID.UnmarshalBinary(data)
|
||||
}
|
||||
|
||||
// Equal checks if two ULID instances are equal by their underlying type
|
||||
// Equal checks if two [ULID] instances are equal by their underlying type.
|
||||
func (u ULID) Equal(other ULID) bool {
|
||||
return u.ULID == other.ULID
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user