Skip to content

feat: like primitive types #172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 13, 2025
Merged

feat: like primitive types #172

merged 6 commits into from
Jul 13, 2025

Conversation

Oudwins
Copy link
Owner

@Oudwins Oudwins commented Jul 13, 2025

closes #163

Summary by CodeRabbit

  • New Features

    • Added support for creating schemas for custom string, boolean, integer, unsigned integer, and float types, enabling validation and parsing of user-defined type aliases.
    • Introduced a new numeric interface combining integer and float constraints for enhanced type support.
  • Tests

    • Introduced comprehensive test coverage for custom type schema processors, covering parsing, validation, option handling, constraints, transformations, and error messages for string, boolean, integer, unsigned integer, and float-like types.
  • Documentation

    • Updated docs to include new generic schema methods for custom primitive types.
    • Added examples demonstrating usage of custom schemas for primitive types with simplified API calls.

Copy link
Contributor

coderabbitai bot commented Jul 13, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces new generic schema constructors—BoolLike, StringLike, FloatLike, IntLike, and UintLike—enabling schema creation for custom types aliased to bool, string, float, int, and uint. Extensive new test files validate these generic schemas for parsing, validation, and option handling with custom types.

Changes

File(s) Change Summary
boolean.go Added BoolLike[T ~bool] for boolean-like type schemas.
string.go Added StringLike[T likeString] for string-like type schemas.
numbers.go Added FloatLike[T Numeric], IntLike[T Numeric], and UintLike[T Numeric] for numeric-like type schemas; updated Numeric type alias.
internals/types.go Added new Numeric interface as union of integer and float constraints.
.../booleanLike_test.go New: Comprehensive tests for BoolLike with custom boolean types.
.../stringLike_test.go New: Comprehensive tests for StringLike with custom string types.
.../floatLike_test.go New: Comprehensive tests for FloatLike with custom float types.
.../intLike_test.go New: Comprehensive tests for IntLike with custom int types.
.../uintLike_test.go New: Comprehensive tests for UintLike with custom uint types.
docs/docs/custom-schemas.md Updated examples to include IntLike usage and simplified EnvSchema example; removed verbose coercer example.
docs/docs/reference.md Added documentation for new generic schema methods: StringLike, IntLike, FloatLike, UintLike, and BoolLike.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SchemaFactory
    participant Schema

    User->>SchemaFactory: Call BoolLike/IntLike/FloatLike/UintLike/StringLike[T](opts)
    SchemaFactory->>Schema: Create Schema[T] with custom coercer and apply options
    Schema-->>User: Return configured Schema[T]
    User->>Schema: Parse/Validate input with Schema[T]
    Schema-->>User: Result or error (with custom type T)
Loading

Possibly related PRs

Poem

A schema for every custom type,
Bool, string, or numbers ripe!
Now rabbits can validate with flair,
No matter the alias, we’re prepared!
With tests galore and types anew,
🐇 hops ahead—schemas for you!
(And all your custom types too!)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c61ccb and 072f57b.

📒 Files selected for processing (1)
  • docs/docs/custom-schemas.md (2 hunks)
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/like-primitive-types

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3152230 and 591c602.

📒 Files selected for processing (8)
  • boolean.go (1 hunks)
  • booleanLike_test.go (1 hunks)
  • floatLike_test.go (1 hunks)
  • intLike_test.go (1 hunks)
  • numbers.go (4 hunks)
  • string.go (1 hunks)
  • stringLike_test.go (1 hunks)
  • uintLike_test.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
boolean.go (2)
utilsOptions.go (1)
  • SchemaOption (64-64)
conf/Coercers.go (1)
  • Coercers (260-260)
string.go (2)
utilsOptions.go (1)
  • SchemaOption (64-64)
conf/Coercers.go (1)
  • Coercers (260-260)
numbers.go (2)
utilsOptions.go (1)
  • SchemaOption (64-64)
conf/Coercers.go (1)
  • Coercers (260-260)
intLike_test.go (7)
numbers.go (2)
  • IntLike (106-120)
  • NumberSchema (16-23)
tutils/testIssueMessages.go (1)
  • VerifyDefaultIssueMessages (14-32)
utilsOptions.go (2)
  • WithCoercer (66-70)
  • Message (13-19)
internals/contexts.go (1)
  • ExecCtx (53-57)
internals/tests.go (6)
  • Required (114-121)
  • GT (236-247)
  • LT (223-234)
  • GTE (210-221)
  • LTE (197-208)
  • EQ (184-195)
zogSchema.go (1)
  • TestFunc (47-49)
zconst/consts.go (1)
  • TypeNumber (42-42)
🔇 Additional comments (12)
numbers.go (4)

10-12: Good type constraint refinement!

The change from constraints.Ordered to constraints.Integer | constraints.Float is more precise and appropriate for numeric types, as it excludes strings that were previously allowed by Ordered.


44-45: Clear deprecation notice added.

The deprecation comment clearly indicates the preferred alternative while maintaining backward compatibility.


50-64: Verify precision implications for integer types.

While the implementation is correct, using FloatLike with integer types could lead to precision loss for large values due to float64's limited mantissa (53 bits). For example, FloatLike[int64] may not accurately represent all int64 values.

Consider documenting this limitation or restricting the constraint to floating-point types only.


106-120: LGTM! Consider documenting type conversion behavior.

The implementation is correct. Note that when used with float types, decimal parts will be truncated, and overflow may occur when casting to smaller integer types.

floatLike_test.go (1)

1-532: Excellent comprehensive test coverage!

The test file thoroughly covers all aspects of the FloatLike function including parsing, validation, schema options, transformations, and edge cases. The table-driven test approach is well-structured and easy to maintain.

uintLike_test.go (1)

1-530: Thorough test coverage with good edge case handling!

The test file comprehensively covers the UintLike function. Particularly good to see the negative value test case (line 28) which verifies proper error handling for invalid inputs.

intLike_test.go (1)

1-530: Comprehensive test suite with proper signed integer handling!

The test file thoroughly covers the IntLike function including proper handling of negative values for signed integers. The test structure is consistent with other test files and provides excellent coverage.

boolean.go (1)

44-58: Clean implementation of BoolLike function!

The generic BoolLike function follows the established pattern and correctly handles boolean type aliases. The constraint T ~bool is appropriate and the coercion logic is straightforward.

string.go (1)

65-79: LGTM! Well-implemented generic function for string-like types.

The StringLike function correctly implements the generic pattern for custom string types. The coercer chain (string coercion followed by type casting) is appropriate, and the implementation follows the established patterns in the codebase.

booleanLike_test.go (1)

1-879: Excellent comprehensive test coverage for BoolLike functionality.

This test file provides thorough coverage of the BoolLike function with well-structured table-driven tests. The tests cover all major scenarios including parsing, validation, schema options, transformations, and error handling. The use of a custom CustomBool type effectively validates the generic functionality.

stringLike_test.go (2)

1-647: Excellent comprehensive test coverage for StringLike functionality.

This test file provides thorough coverage of the StringLike function with well-structured tests covering all string-specific validations. The test patterns are consistent and comprehensive.


346-350: UUID Test Case Is Valid Under Current Regex

The uuidRegex used by is.UUIDv4 matches any 8-4-4-4-12 hex pattern without enforcing the “4” version nibble. Therefore, "123e4567-e89b-12d3-a456-426614174000" correctly passes the existing validation and the test behaves as expected. No changes are required.

Comment on lines +171 to +185
func UintLike[T Numeric](opts ...SchemaOption) *NumberSchema[T] {
s := &NumberSchema[T]{
coercer: func(data any) (any, error) {
x, err := conf.Coercers.Uint(data)
if err != nil {
return nil, err
}
return T(x.(uint)), nil
},
}
for _, opt := range opts {
opt(s)
}
return s
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential overflow issue with signed types.

The Numeric constraint includes signed types, but coercing through uint can cause unexpected behavior. For example, UintLike[int8] with input 200 would overflow to -56.

Consider either:

  1. Creating a separate constraint for unsigned types only
  2. Adding overflow validation before the cast
  3. Documenting this behavior clearly

Example of the issue:

// This would result in -56 due to overflow
schema := UintLike[int8]()
var result int8
schema.Parse(200, &result)
🤖 Prompt for AI Agents
In numbers.go around lines 171 to 185, the UintLike function uses a Numeric
constraint that includes signed types, but coercion is done through uint which
can cause overflow issues when casting back to signed types. To fix this, either
create a separate constraint that only allows unsigned types for UintLike, or
add explicit overflow checks before casting to T to prevent invalid values, or
clearly document this behavior so users are aware of the potential overflow risk
when using signed types.

Copy link

Deploying zog with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5ccbae0
Status: ✅  Deploy successful!
Preview URL: https://44bfbf1f.zog-3a0.pages.dev
Branch Preview URL: https://feat-like-primitive-types.zog-3a0.pages.dev

View logs

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
docs/docs/custom-schemas.md (2)

19-19: Avoid weak intensifiers; tighten the wording

The adverb “quite” adds little value here. Consider a crisper alternative.

-This is quite simple to do for the supported primitive types (string, number, boolean).
+This is straightforward for the supported primitive types (string, number, boolean).

48-48: Minor lint issue: hard tabs flagged by markdownlint

Tabs inside fenced code blocks still trigger MD010. Replace with spaces or disable the rule locally to keep CI green.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 591c602 and 5ccbae0.

📒 Files selected for processing (2)
  • docs/docs/custom-schemas.md (3 hunks)
  • docs/docs/reference.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/docs/reference.md
🧰 Additional context used
🪛 LanguageTool
docs/docs/custom-schemas.md

[style] ~19-~19: As an alternative to the over-used intensifier ‘quite’, consider replacing this phrase.
Context: ...om Schemas for Primitive Types This is quite simple to do for the supported primitive types...

(EN_WEAK_ADJECTIVE)

🪛 markdownlint-cli2 (0.17.2)
docs/docs/custom-schemas.md

32-32: Hard tabs
Column: 1

(MD010, no-hard-tabs)


33-33: Hard tabs
Column: 1

(MD010, no-hard-tabs)


37-37: Hard tabs
Column: 1

(MD010, no-hard-tabs)


48-48: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🔇 Additional comments (1)
docs/docs/custom-schemas.md (1)

37-37: Looks good – matches new API

z.StringLike[Env]() demonstrates the intended usage of the new generic helper and reads well in the example.

@Oudwins Oudwins merged commit 126d79b into master Jul 13, 2025
8 of 9 checks passed
@Oudwins Oudwins deleted the feat/like-primitive-types branch July 13, 2025 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support Generics-based Primitive Aliases
1 participant