Skip to content

Commit

Permalink
FEATURE: Added support for a Parsing interface to allow for custom ve…
Browse files Browse the repository at this point in the history
…rsion parsing (#2)

- **FEATURE:** Added documentation for the configuration options: `WithStrictAdherence`.
- **DEBT:** Added additional functional tests to improve code coverage.
- **DEBT:** Refactored the benchmark tests to correctly measure performance.
- **DEFECT:** Corrected various documentation issues.
  • Loading branch information
mprimeaux authored Nov 25, 2024
1 parent 333c388 commit 7d36979
Show file tree
Hide file tree
Showing 12 changed files with 1,117 additions and 579 deletions.
21 changes: 20 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ Date format: `YYYY-MM-DD`
### Fixed
### Security

---
## [1.1.0] - 2024-10-25

### Added
- **FEATURE:** Added support for a `Parsing` interface to allow for custom version parsing.
- **FEATURE:** Added documentation for the configuration options: `WithStrictAdherence`.

### Changed
- **DEBT:** Added additional functional tests to improve code coverage.
- **DEBT:** Refactored the benchmark tests to correctly measure performance.

### Deprecated
### Removed
### Fixed
- **DEFECT:** Corrected various documentation issues.

### Security

---
## [1.0.0] - 2024-10-24

Expand All @@ -28,7 +46,8 @@ Date format: `YYYY-MM-DD`
### Fixed
### Security

[Unreleased]: https://github.com/sixafter/semver/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/sixafter/semver/compare/v1.1.0...HEAD
[1.0.0]: https://github.com/sixafter/semver/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/sixafter/semver/compare/d63ed577e7e841fb2209cfdcf4269fac6a57c85e...v1.0.0

[MUST]: https://datatracker.ietf.org/doc/html/rfc2119
Expand Down
73 changes: 34 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,60 +15,57 @@ A Semantic Versioning 2.0.0 compliant parser and utility library written in Go.

The `semver` library offers a comprehensive and efficient solution for working with Semantic Versioning 2.0.0. Key features include:

### Zero Dependencies
- Lightweight implementation with no external dependencies beyond the standard library.
- **Zero Dependencies**
- Lightweight implementation with no external dependencies beyond the standard library.

### Full Compliance
- Parses and validates semantic versions according to the [Semantic Versioning 2.0.0](https://semver.org) specification.
- **Full Compliance**
- Parses and validates semantic versions according to the [Semantic Versioning 2.0.0](https://semver.org) specification.

### Version Parsing and Validation
- Parse semantic version strings into structured `Version` objects.
- Automatically validate version strings for correctness, including:
- **Version Parsing and Validation**
- Parses semantic version strings into structured `Version` objects.
- Automatically validates version strings for correctness, including:
- Major, minor, and patch components.
- Pre-release identifiers (e.g., `alpha`, `beta`, `rc.1`).
- Build metadata (e.g., `build.123`).
- Enforces no leading zeroes in numeric components.

### Version Comparison
- Supports comparison of versions using Semantic Versioning rules:
- **Customizable**
- Define your own parser.
- Strict mode for enforcing strict version format rules.

- **Version Comparison**
- Supports comparison of versions using Semantic Versioning rules:
- `Compare`: Returns -1, 0, or 1 for less than, equal to, or greater than comparisons.
- Convenient helper methods:
- `LessThan`, `LessThanOrEqual`
- `GreaterThan`, `GreaterThanOrEqual`
- `Equal`
- Correctly handles precedence rules for pre-release versions and build metadata.
- Convenient helper methods: `LessThan`, `LessThanOrEqual`, `GreaterThan`, `GreaterThanOrEqual`, `Equal`.
- Correctly handles precedence rules for pre-release versions and build metadata.

### Version Ranges
- Flexible range functionality for evaluating version constraints:
- **Version Ranges**
- Flexible range functionality for evaluating version constraints:
- Define complex version ranges using a familiar syntax (e.g., `">=1.0.0 <2.0.0"`).
- Determine whether a version satisfies a given range.
- Combine multiple ranges for advanced constraints (e.g., `">=1.2.3 || <1.0.0-alpha"`).
- Useful for dependency management, release gating, and compatibility checks.

### Version Construction
- Create `Version` instances programmatically using the `NewVersion` constructor.
- Supports detailed customization of pre-release identifiers and build metadata.
- Useful for dependency management, release gating, and compatibility checks.

### JSON Support
- Seamlessly marshal and unmarshal `Version` objects to and from JSON.
- Works with `encoding/json` for easy integration with APIs and configuration files.
- **JSON Support**
- Seamlessly marshal and unmarshal `Version` objects to and from JSON.
- Works with `encoding/json` for easy integration with APIs and configuration files.

### Database Support
- Compatible with `database/sql`:
- **Database Support**
- Compatible with `database/sql`:
- Implements `driver.Valuer` to store `Version` in databases.
- Implements `sql.Scanner` to retrieve `Version` from databases.

### Encoding and Decoding
- Implements standard Go interfaces:
- **Encoding and Decoding**
- Implements standard Go interfaces:
- `encoding.TextMarshaler` and `encoding.TextUnmarshaler` for text encoding.
- `encoding.BinaryMarshaler` and `encoding.BinaryUnmarshaler` for binary encoding.

### Performance Optimizations
- Efficient parsing and comparison with minimal memory allocations.
- Designed for high performance with concurrent workloads.
- **Performance Optimizations**
- Efficient parsing and comparison with minimal memory allocations.
- Designed for high performance with concurrent workloads.

### Well-Tested
- Comprehensive test coverage, including:
- **Well-Tested**
- Comprehensive test coverage, including:
- Functional tests for all features.
- Benchmarks to validate performance optimizations.
- Detailed tests for range evaluation, parsing, and edge cases.
Expand Down Expand Up @@ -209,13 +206,11 @@ goos: darwin
goarch: arm64
pkg: github.com/sixafter/semver
cpu: Apple M2 Ultra
BenchmarkParseVersionSerial-24 1577372 744.4 ns/op 608 B/op 16 allocs/op
BenchmarkParseVersionConcurrent-24 3696235 337.3 ns/op 608 B/op 16 allocs/op
BenchmarkParseVersionAllocations-24 7339026 162.1 ns/op 160 B/op 4 allocs/op
BenchmarkParseVersionLargeSerial-24 208 5825681 ns/op 4640079 B/op 120000 allocs/op
BenchmarkParseVersionLargeConcurrent-24 589 2047877 ns/op 4640185 B/op 120000 allocs/op
BenchmarkParseVersionSerial-24 9170428 123.1 ns/op 128 B/op 2 allocs/op
BenchmarkParseVersionConcurrent-24 17886765 68.35 ns/op 128 B/op 2 allocs/op
BenchmarkParseVersionAllocations-24 7576131 157.2 ns/op 144 B/op 4 allocs/op
PASS
ok github.com/sixafter/semver 8.366s
ok github.com/sixafter/semver 4.109s
```
</details>

Expand Down
111 changes: 111 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) 2024 Six After, Inc
//
// This source code is licensed under the Apache 2.0 License found in the
// LICENSE file in the root directory of this source tree.

package semver

// ConfigOptions holds the configurable options for the Parser.
// It is used with the Function Options pattern.
type ConfigOptions struct {
Strict bool
}

// Config holds the runtime configuration for the parser.
//
// It is immutable after initialization.
type Config interface {
// StrictAdherence returns a boolean value indicating whether strict adherence is enabled.
// This method is used to determine if the configuration should follow strict rules,
// such as requiring full compliance with the Semantic Versioning specification.
// When enabled, parsing or processing might be more stringent, rejecting inputs that
// do not fully comply with the expected standards.
//
// Returns:
// - bool: true if strict adherence is enabled, false otherwise.
//
// Example usage:
//
// var config Config = NewConfig()
// if config.StrictAdherence() {
// fmt.Println("Strict adherence is enabled.")
// } else {
// fmt.Println("Strict adherence is disabled.")
// }
StrictAdherence() bool
}

// Configuration defines the interface for retrieving parser configuration.
type Configuration interface {
// Config returns the runtime configuration of the parser.
Config() Config
}

type runtimeConfig struct {
strict bool
}

// Option defines a function type for configuring the Parser.
// It allows for flexible and extensible configuration by applying
// various settings to the ConfigOptions during Parser initialization.
type Option func(*ConfigOptions)

// WithStrictAdherence sets the strict adherence value for the configuration.
// This option can be used to enable or disable strict mode, which affects the way
// certain rules are enforced during parsing or processing.
//
// Setting strict adherence to true can be used to enforce more rigid compliance
// with versioning rules or configuration standards. When set to false, the parser
// may allow some flexibility in handling certain inputs.
//
// Parameters:
// - value: A boolean indicating whether strict adherence should be enabled (true) or disabled (false).
//
// Returns:
// - Option: A functional option that can be passed to a configuration function to modify behavior.
//
// Example usage:
//
// parser, err := NewParser(WithStrictAdherence(true))
// if err != nil {
// log.Fatalf("Failed to create parser: %v", err)
// }
//
// // Use the parser with strict adherence enabled
// version, err := parser.Parse("1.0.0")
// if err != nil {
// log.Fatalf("Failed to parse version: %v", err)
// }
// fmt.Printf("Parsed version: %v\n", version)
func WithStrictAdherence(value bool) Option {
return func(o *ConfigOptions) {
o.Strict = value
}
}

// StrictAdherence returns a boolean value indicating whether strict adherence is enabled.
// This method is used to determine if the configuration should follow strict rules,
// such as requiring full compliance with the Semantic Versioning specification.
// When enabled, parsing or processing might be more stringent, rejecting inputs that
// do not fully comply with the expected standards.
//
// Returns:
// - bool: true if strict adherence is enabled, false otherwise.
//
// Example usage:
//
// var config Config = NewConfig()
// if config.StrictAdherence() {
// fmt.Println("Strict adherence is enabled.")
// } else {
// fmt.Println("Strict adherence is disabled.")
// }
func (c *runtimeConfig) StrictAdherence() bool {
return c.strict
}

func buildRuntimeConfig(opts *ConfigOptions) (*runtimeConfig, error) {
return &runtimeConfig{
strict: opts.Strict,
}, nil
}
29 changes: 29 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024 Six After, Inc
//
// This source code is licensed under the Apache 2.0 License found in the
// LICENSE file in the root directory of this source tree.

package semver

import (
"testing"

"github.com/stretchr/testify/assert"
)

// TestGetConfig tests the Config() method of the generator.
func TestGetConfig(t *testing.T) {
t.Parallel()
is := assert.New(t)

gen, err := NewParser(WithStrictAdherence(true))
is.NoError(err, "NewGenerator() should not return an error with the default alphabet")

// Assert that generator implements Configuration interface
config, ok := gen.(Configuration)
is.True(ok, "Parser should implement Configuration interface")

runtimeConfig := config.Config()

is.True(runtimeConfig.StrictAdherence(), "Config.StrictAdherence should be true")
}
Loading

0 comments on commit 7d36979

Please sign in to comment.