Skip to content

Conversation

@ttypic
Copy link
Contributor

@ttypic ttypic commented Aug 19, 2025

Array<Object> can't be cast to Array<ObjectMessages> even if every element is an instance of ObjectMessages, so it's safer to use map

Summary by CodeRabbit

  • Refactor
    • Improved serialization safety by replacing unchecked array casts with per-element casting and safe iteration.
    • Removed suppression of unchecked-cast warnings for clearer type safety.
    • No changes to public APIs or user-visible behavior; improves internal robustness and maintainability.

@ttypic ttypic requested a review from sacOO7 August 19, 2025 10:27
@coderabbitai
Copy link

coderabbitai bot commented Aug 19, 2025

Walkthrough

Removed a file-level unchecked-cast suppression and replaced two array-wide casts with per-element casts via map in writeMsgpackArray and asJsonArray within DefaultSerialization.kt. Logic flow and public API remain unchanged.

Changes

Cohort / File(s) Summary of Changes
Serialization casting adjustments
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt
Removed @file:Suppress("UNCHECKED_CAST"). Replaced array-wide unsafe casts with per-element casts using map in writeMsgpackArray and asJsonArray; iterated over List. No API/signature changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I nibbled at casts, one by one,
Trading “trust me” for safer fun.
Arrays became lists—hop hop, neat—
Each element checked, a tidy treat.
Burrow secure, no warnings bite;
Serialization sleeps snug tonight. 🥕🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/array-casting

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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@github-actions github-actions bot temporarily deployed to staging/pull/1152/features August 19, 2025 10:28 Inactive
@github-actions github-actions bot temporarily deployed to staging/pull/1152/javadoc August 19, 2025 10:30 Inactive
Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

lgtm

sacOO7

This comment was marked as duplicate.

@sacOO7 sacOO7 self-requested a review August 19, 2025 10:45
Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

Can you also remove

@file:Suppress("UNCHECKED_CAST")

from top of the file

Copy link

@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: 0

🧹 Nitpick comments (2)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (2)

24-27: Optional: avoid the intermediate list while preserving “fail-before-write” semantics.

Current approach allocates a List. If you want to drop that allocation yet still ensure nothing is written to the packer unless all elements are valid, a two-pass validation works. Trade-off: slightly more code and two casts per element.

Apply this diff if you prefer the two-pass approach:

-    val objectMessages = objects.map { it as ObjectMessage }
-    packer.packArrayHeader(objectMessages.size)
-    objectMessages.forEach { it.writeMsgpack(packer) }
+    // First pass: validate elements (throws before any write on invalid element)
+    for (o in objects) {
+      o as ObjectMessage
+    }
+    // Second pass: write
+    packer.packArrayHeader(objects.size)
+    for (o in objects) {
+      (o as ObjectMessage).writeMsgpack(packer)
+    }

37-43: Optional: remove the temporary list to reduce allocations.

For the JSON path, you can avoid the intermediate List and directly build the JsonArray. Since JsonArray is only returned on success, partially filled arrays on exception aren’t observable to callers.

Apply this diff if you prefer the single-pass approach:

-    val objectMessages = objects.map { it as ObjectMessage }
-
-    val jsonArray = JsonArray()
-    for (objectMessage in objectMessages) {
-      jsonArray.add(objectMessage.toJsonObject())
-    }
-    return jsonArray
+    val jsonArray = JsonArray()
+    for (o in objects) {
+      val objectMessage = o as ObjectMessage
+      jsonArray.add(objectMessage.toJsonObject())
+    }
+    return jsonArray
📜 Review details

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

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2c36548 and e52e002.

📒 Files selected for processing (1)
  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.
📚 Learning: 2025-06-23T14:18:25.315Z
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:25-29
Timestamp: 2025-06-23T14:18:25.315Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class methods like writeMsgpackArray will have their type signatures updated to be non-nullable since the calling sites ensure objects are never null when passed to these methods.

Applied to files:

  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt
📚 Learning: 2025-06-23T14:14:17.847Z
Learnt from: sacOO7
PR: ably/ably-java#1106
File: live-objects/src/main/kotlin/io/ably/lib/objects/serialization/Serialization.kt:38-46
Timestamp: 2025-06-23T14:14:17.847Z
Learning: In the ably-java codebase, the DefaultLiveObjectSerializer class uses intentional unsafe casting (`objects as Array<ObjectMessage>`) without type validation in both writeMsgpackArray and asJsonArray methods. This is a deliberate design decision to keep the dynamically-loaded class simple and let ClassCastException occur naturally for type mismatches.

Applied to files:

  • live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: check-liveobjects
  • GitHub Check: check-rest-okhttp
  • GitHub Check: check-realtime-okhttp
  • GitHub Check: check-realtime
  • GitHub Check: check (24)
  • GitHub Check: check (21)
  • GitHub Check: check-rest
  • GitHub Check: check (29)
  • GitHub Check: build
  • GitHub Check: check (19)
  • GitHub Check: check
🔇 Additional comments (3)
live-objects/src/main/kotlin/io/ably/lib/objects/serialization/DefaultSerialization.kt (3)

24-27: Safer per-element cast avoids relying on array reified type — good change.

Switching from an array-wide cast to per-element casts via map removes the brittle dependency on the runtime component type of the array. This aligns with the PR objective.


37-43: LGTM: consistent per-element cast for JSON path as well.

Mirrors the MessagePack path, keeping semantics aligned.


24-27: Confirm intentional change to per-element type casting behavior
The new implementation replaces the previous array-wide cast (objects as Array<ObjectMessage>) with per-element casts (it as ObjectMessage), shifting failure from the initial cast to individual elements during packing. This alters when and how a ClassCastException is raised.

Please verify that:

  • This behavioral change is desired and documented.
  • No existing tests or code rely on the old “fail-fast” array-cast semantics.

Recommended checks (run in the repo root):

# Find tests using @Test(expected=ClassCastException)
rg -n -P --glob '*Test*' '@Test\s*\(\s*expected\s*=\s*ClassCastException'

# Find assertThrows usage for ClassCastException
rg -n -P --glob '*Test*' 'assertThrows\s*(ClassCastException|TypeCastException)'

# Find any remaining array-wide casts to ObjectMessage
rg -n -P 'as\s+Array<\s*ObjectMessage\s*>'

If you do find tests expecting the old behavior, update or remove them to align with per-element casting.
— DefaultSerialization.kt (lines 24–27)

Copy link
Collaborator

@sacOO7 sacOO7 left a comment

Choose a reason for hiding this comment

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

lgtm

@ttypic ttypic merged commit edf8568 into main Aug 19, 2025
13 checks passed
@ttypic ttypic deleted the fix/array-casting branch August 19, 2025 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants