Skip to content

feat: support getIn on Package#35

Merged
fengmk2 merged 8 commits intomasterfrom
add-get-in-on-package
Dec 6, 2025
Merged

feat: support getIn on Package#35
fengmk2 merged 8 commits intomasterfrom
add-get-in-on-package

Conversation

@fengmk2
Copy link
Member

@fengmk2 fengmk2 commented Dec 5, 2025

Summary by CodeRabbit

  • New Features
    • Added getIn(), getInPosition(), and getBufferIn() to retrieve parsed values, positional ranges, and raw buffer data for specified paths.
  • Tests
    • Added tests validating getIn() behavior for valid paths and error handling for invalid/empty paths.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings December 5, 2025 16:41
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 5, 2025

Warning

Rate limit exceeded

@fengmk2 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 16 minutes and 12 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 71a3278 and e76822f.

⛔ Files ignored due to path filters (2)
  • __test__/__snapshots__/index.spec.ts.snap is excluded by !**/*.snap
  • __test__/__snapshots__/package.spec.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (5)
  • __test__/index.spec.ts (1 hunks)
  • __test__/package.spec.ts (1 hunks)
  • index.d.ts (1 hunks)
  • js/package.ts (1 hunks)
  • src/package.rs (2 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds native byte-range lookup and JS wrappers to read nested package data by path: exposes Rust JSON helpers, implements get_in_position in Rust, adds a JS Package that provides getIn/getBufferIn, updates exports, and adds tests validating behavior.

Changes

Cohort / File(s) Summary
Tests
__test__/index.spec.ts
Updated import to ../js/index.js and added two tests: one asserting getIn(['versions','1.0.0','name']) returns "obug" and snapshots the version object; one asserting getIn throws for empty path arrays.
Type declarations
index.d.ts
Added getInPosition(paths: Array<string>): [number, number] | null signature on Package.
JS export layer
js/index.ts
Changed re-export source from ../index.js to ./package.js; kept export * from './builder.js'.
JS Package wrapper
js/package.ts
New module: re-exports types and defines export class Package extends NativePackage with constructor(data: Buffer), getIn<T = unknown>(paths: string[]): T | undefined (parses JSON from sub-buffer), and getBufferIn(paths: string[]): Buffer | undefined (returns buffer slice using native positions).
Rust JSON utilities
src/json.rs
Broadened visibility: build_pointers and check_paths changed to pub(crate) for crate-wide use.
Rust Package method
src/package.rs
Added pub fn get_in_position(&self, paths: Vec<String>) -> Result<Option<(u32, u32)>> using json::check_paths and json::build_pointers to locate value byte ranges; imported crate::json.

Sequence Diagram(s)

sequenceDiagram
  participant JS as JS Package
  participant Native as Native (WASM/Rust)
  participant JSON as json helpers (build_pointers/check_paths)
  participant Root as Package root (internal pointer lookup)

  JS->>JS: getIn(paths)
  JS->>JS: getBufferIn(paths)
  JS->>Native: getInPosition(paths)   -- RPC/bridge call
  Native->>JSON: check_paths(paths)
  JSON-->>Native: validated pointers
  Native->>Root: root.pointer(pointers)
  Root-->>Native: Some(start,end) or None
  Native-->>JS: [start,end] or null
  JS->>JS: if positions -> slice buffer -> JSON.parse -> return value
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

  • Review buffer slicing and JSON.parse handling in js/package.ts, including the @ts-expect-error usage.
  • Verify correctness and edge-case handling in src/package.rs::get_in_position and dependency on json::build_pointers/check_paths.
  • Ensure exported types/paths in js/index.ts and index.d.ts match implementation.

Possibly related PRs

Suggested labels

enhancement

Poem

🐰 A byte, a hop, a hidden key,
Paths unwound from root to tree,
Rust plants pointers, JS takes a bite,
Buffers dance in soft moonlight,
Hooray — data found, snug and right!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: support getIn on Package' clearly describes the primary change: adding support for a getIn method on the Package class.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link

Summary of Changes

Hello @fengmk2, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the Package class by adding a powerful getIn method, which allows developers to precisely extract nested data points from package metadata using a clear path-based approach. This feature is backed by a high-performance Rust implementation that efficiently locates the exact byte range of the requested data, providing both parsed JSON and raw buffer access, thereby improving data retrieval capabilities and overall efficiency.

Highlights

  • New getIn Method: Introduced a new getIn method to the Package class, enabling efficient retrieval of deeply nested values from package metadata using a path array. This method parses the retrieved data as JSON.
  • Raw Buffer Retrieval: Added a getBufferIn method that complements getIn, allowing users to retrieve the raw byte buffer of a value at a specified path without immediate JSON parsing.
  • Rust Backend for Performance: The core logic for locating values by path is implemented in Rust with a new get_in_position method, which returns the start and end byte offsets of the target value within the package's JSON data. This leverages Rust's performance for efficient data access.
  • Module Restructuring and Type Definitions: The JavaScript module exports were updated to reflect the new Package class structure, and TypeScript definitions were extended to include the new getInPosition method.
  • Comprehensive Testing: New test cases have been added to validate the functionality of the getIn method, including handling of valid paths and error conditions like empty path arrays, ensuring robustness.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a getIn method on the Package class, allowing retrieval of nested properties from the package metadata. The implementation is sound, leveraging a native Rust function for performance and providing a clean JavaScript wrapper. The changes are well-tested. I've provided a couple of suggestions to enhance code clarity and follow idiomatic conventions in both TypeScript and Rust.

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

📦 napi-rs Build Size Comparison

File Base Size PR Size Diff %
📈 packument.linux-x64-gnu.node 853.82 KB 869.82 KB +16.00 KB +1.87%

Total: 853.82 KB → 869.82 KB (+16.00 KB, +1.87%)

Compared using x86_64-unknown-linux-gnu target

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds getIn functionality to the Package class, enabling convenient retrieval of nested values from package metadata by path. The implementation follows the existing pattern from JSONBuilder, adding a native getInPosition method in Rust and wrapping it with TypeScript convenience methods.

Key Changes

  • Added get_in_position method to the Rust Package implementation that returns byte positions for values at specified paths
  • Created a TypeScript Package wrapper class that extends the native implementation with getIn and getBufferIn convenience methods
  • Refactored check_paths and build_pointers helper functions to be reusable across modules

Reviewed changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/package.rs Added get_in_position method to return byte positions of nested values using JSON pointer navigation
src/json.rs Made check_paths and build_pointers helpers pub(crate) for reuse in package.rs
js/package.ts New TypeScript wrapper class extending native Package with getIn/getBufferIn methods
js/index.ts Updated exports to use the TypeScript wrapper instead of native class directly
index.d.ts Added TypeScript type definition for getInPosition method
test/index.spec.ts Added tests for the new getIn functionality and error handling
test/snapshots/index.spec.ts.snap Added snapshot for version metadata retrieval test

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: MK (fengmk2) <fengmk2@gmail.com>
Copilot AI review requested due to automatic review settings December 5, 2025 16:48
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: MK (fengmk2) <fengmk2@gmail.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (4)

test/snapshots/index.spec.ts.snap:259

  • The snapshot name "should get in work" doesn't match the test name "should getIn work correctly". This mismatch will cause test failures. The snapshot name should be should getIn work correctly 1.
    test/index.spec.ts:154
  • The test doesn't cover the case where getIn() returns undefined for a non-existent path. Consider adding a test case like:
expect(pkg.getIn(['nonexistent', 'path'])).toBeUndefined()

test/index.spec.ts:154

  • Missing test coverage for getBufferIn() method. Consider adding a test to verify it returns the correct Buffer slice:
const buffer = pkg.getBufferIn(['versions', '1.0.0', 'name'])
expect(buffer?.toString()).toEqual('"obug"')

test/index.spec.ts:154

  • Missing test coverage for getInPosition() method. Consider adding a test to verify it returns the correct position tuple:
const position = pkg.getInPosition(['versions', '1.0.0', 'name'])
expect(position).toEqual(expect.arrayContaining([expect.any(Number), expect.any(Number)]))

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link

github-actions bot commented Dec 5, 2025

⚡ Benchmark Results

Click to expand benchmark output
┌─────────┬──────────────────────────────────────────────────────────────────────┬─────────────────────┬───────────────────────┬────────────────────────┬────────────────────────┬─────────┐
│ (index) │ Task name                                                            │ Latency avg (ns)    │ Latency med (ns)      │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
├─────────┼──────────────────────────────────────────────────────────────────────┼─────────────────────┼───────────────────────┼────────────────────────┼────────────────────────┼─────────┤
│ 0       │ 'JSONParse small data readme string (117KB)'                         │ '541820 ± 0.73%'    │ '500011 ± 13124'      │ '1880 ± 0.56%'         │ '2000 ± 54'            │ 1846    │
│ 1       │ 'sonic-rs small data readme string (117KB)'                          │ '125233 ± 0.25%'    │ '120966 ± 681.00'     │ '8053 ± 0.17%'         │ '8267 ± 47'            │ 7986    │
│ 2       │ 'sonic-rs small data readme string with position (117KB)'            │ '146169 ± 0.35%'    │ '140343 ± 862.00'     │ '6916 ± 0.20%'         │ '7125 ± 44'            │ 6842    │
│ 3       │ 'sonic-rs small data readme JSON buffer with position (117KB)'       │ '104098 ± 0.15%'    │ '102782 ± 151.00'     │ '9628 ± 0.07%'         │ '9729 ± 14'            │ 9607    │
│ 4       │ 'JSONParse large data readme string (22MB)'                          │ '113565525 ± 1.44%' │ '112298718 ± 331385'  │ '9 ± 1.09%'            │ '9 ± 0'                │ 64      │
│ 5       │ 'sonic-rs large data readme string (22MB)'                           │ '18027906 ± 0.10%'  │ '18014677 ± 44253'    │ '55 ± 0.10%'           │ '56 ± 0'               │ 64      │
│ 6       │ 'sonic-rs large data readme string with position (22MB)'             │ '17966404 ± 0.25%'  │ '17931877 ± 55974'    │ '56 ± 0.24%'           │ '56 ± 0'               │ 64      │
│ 7       │ 'sonic-rs large data readme JSON buffer with position (22MB)'        │ '17985184 ± 0.16%'  │ '17971352 ± 53691'    │ '56 ± 0.16%'           │ '56 ± 0'               │ 64      │
│ 8       │ 'JSONParse super large data readme string (89M)'                     │ '392474966 ± 1.08%' │ '382169189 ± 3088574' │ '3 ± 1.05%'            │ '3 ± 0'                │ 64      │
│ 9       │ 'sonic-rs super large data readme string (89M)'                      │ '66243501 ± 0.07%'  │ '66223815 ± 114925'   │ '15 ± 0.07%'           │ '15 ± 0'               │ 64      │
│ 10      │ 'sonic-rs super large data readme string with position (89M)'        │ '66328426 ± 0.06%'  │ '66314609 ± 134302'   │ '15 ± 0.06%'           │ '15 ± 0'               │ 64      │
│ 11      │ 'sonic-rs super large data readme JSON buffer with position (89M)'   │ '66269320 ± 0.10%'  │ '66264792 ± 161952'   │ '15 ± 0.10%'           │ '15 ± 0'               │ 64      │
│ 12      │ 'JSONParse big readme string (229KB, 64KB readme)'                   │ '730707 ± 3.02%'    │ '695091 ± 8587.0'     │ '1423 ± 0.39%'         │ '1439 ± 18'            │ 1369    │
│ 13      │ 'sonic-rs big readme string (229KB, 64KB readme)'                    │ '245126 ± 0.41%'    │ '240189 ± 2434.0'     │ '4104 ± 0.17%'         │ '4163 ± 42'            │ 4080    │
│ 14      │ 'sonic-rs big readme string with position (229KB, 64KB readme)'      │ '276976 ± 0.24%'    │ '273401 ± 3037.0'     │ '3621 ± 0.13%'         │ '3658 ± 41'            │ 3611    │
│ 15      │ 'sonic-rs big readme JSON buffer with position (229KB, 64KB readme)' │ '208858 ± 0.09%'    │ '206416 ± 511.50'     │ '4792 ± 0.07%'         │ '4845 ± 12'            │ 4788    │
│ 16      │ 'JSONParse large data add version (22MB)'                            │ '269865769 ± 0.12%' │ '269826071 ± 706014'  │ '4 ± 0.12%'            │ '4 ± 0'                │ 64      │
│ 17      │ 'sonic-rs large data add version (22MB)'                             │ '49800876 ± 0.76%'  │ '48868747 ± 672688'   │ '20 ± 0.76%'           │ '20 ± 0'               │ 64      │
│ 18      │ 'JSONParse super large data add version (89M)'                       │ '791693993 ± 0.16%' │ '791753373 ± 2045254' │ '1 ± 0.16%'            │ '1 ± 0'                │ 64      │
│ 19      │ 'sonic-rs super large data add version (89M)'                        │ '193058748 ± 0.12%' │ '192835315 ± 515174'  │ '5 ± 0.12%'            │ '5 ± 0'                │ 64      │
└─────────┴──────────────────────────────────────────────────────────────────────┴─────────────────────┴───────────────────────┴────────────────────────┴────────────────────────┴─────────┘

Memory Usage:
  JSONParse description (22M): 472.3 MB (min: 471.6 MB, max: 473.1 MB)
  JSONParse description (89M): 764.8 MB (min: 763.3 MB, max: 766.0 MB)
  SonicJSONParse description (22M): 91.0 MB (min: 90.0 MB, max: 91.7 MB)
  SonicJSONParse description (89M): 159.0 MB (min: 157.6 MB, max: 159.6 MB)

Memory Usage:
  JSONParse add version (22M): 416.2 MB (min: 413.1 MB, max: 420.6 MB)
  JSONParse add version (89M): 778.1 MB (min: 777.5 MB, max: 779.0 MB)
  SonicJSONParse add version (22M): 182.1 MB (min: 181.2 MB, max: 183.1 MB)
  SonicJSONParse add version (89M): 408.9 MB (min: 338.8 MB, max: 427.6 MB)

Memory Usage:
  JSONParse get property value (22M): 489.0 MB (min: 488.7 MB, max: 489.4 MB)
  JSONParse get property value (89M): 830.6 MB (min: 766.4 MB, max: 874.6 MB)
  SonicJSONParse get property value (22M): 93.5 MB (min: 92.3 MB, max: 94.2 MB)
  SonicJSONParse get property value (89M): 159.5 MB (min: 158.9 MB, max: 160.5 MB)

## Benchmarking JSONParse with @primer/react.json
- Data size: 89MB
- GC: enabled

JSONParse add version (@primer/react.json) #1 time: 850ms
JSONParse add version (@primer/react.json) #2 time: 789ms
JSONParse add version (@primer/react.json) #3 time: 826ms
JSONParse add version (@primer/react.json) #4 time: 796ms
JSONParse add version (@primer/react.json) #5 time: 798ms

[GC] total(ms)= 134.48 count= 24 avg(ms)= 5.60 byKind= {
  scavenge: 55.22804199997336,
  markSweepCompact: 77.5143139999127,
  incremental: 1.738703000068199,
  weakc: 0,
  unknown: 0
}

## Benchmarking SonicJSONParse with @primer/react.json
- Data size: 89MB
- GC: enabled

SonicJSONParse add version (@primer/react.json) #1 time: 192ms
SonicJSONParse add version (@primer/react.json) #2 time: 194ms
SonicJSONParse add version (@primer/react.json) #3 time: 194ms
SonicJSONParse add version (@primer/react.json) #4 time: 195ms
SonicJSONParse add version (@primer/react.json) #5 time: 194ms

[GC] total(ms)= 4.00 count= 6 avg(ms)= 0.67 byKind= {
  scavenge: 0,
  markSweepCompact: 3.3919869999517687,
  incremental: 0.6059329999261536,
  weakc: 0,
  unknown: 0
}

## Benchmarking JSONParse with @primer/react.json
- Data size: 89MB
- GC: enabled

JSONParse get name of @primer/react.json: '@primer/react'
JSONParse get property value (@primer/react.json) #1 time: 434ms
JSONParse get property value (@primer/react.json) #2 time: 410ms
JSONParse get property value (@primer/react.json) #3 time: 425ms
JSONParse get property value (@primer/react.json) #4 time: 396ms
JSONParse get property value (@primer/react.json) #5 time: 373ms

[GC] total(ms)= 253.52 count= 26 avg(ms)= 9.75 byKind= {
  scavenge: 217.18430100003025,
  markSweepCompact: 35.105833999987226,
  incremental: 1.2283779999706894,
  weakc: 0,
  unknown: 0
}

## Benchmarking SonicJSONParse with @primer/react.json
- Data size: 89MB
- GC: enabled

SonicJSONParse get name of @primer/react.json: '@primer/react'
SonicJSONParse get property value (@primer/react.json) #1 time: 0ms
SonicJSONParse get property value (@primer/react.json) #2 time: 0ms
SonicJSONParse get property value (@primer/react.json) #3 time: 0ms
SonicJSONParse get property value (@primer/react.json) #4 time: 0ms
SonicJSONParse get property value (@primer/react.json) #5 time: 0ms

[GC] total(ms)= 1.53 count= 2 avg(ms)= 0.76 byKind= {
  scavenge: 0,
  markSweepCompact: 1.332592000020668,
  incremental: 0.19272099999943748,
  weakc: 0,
  unknown: 0
}

Benchmark ran on x86_64-unknown-linux-gnu target

@fengmk2 fengmk2 merged commit de55f93 into master Dec 6, 2025
38 checks passed
@fengmk2 fengmk2 deleted the add-get-in-on-package branch December 6, 2025 01:29
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.

2 participants