Skip to content

Commit 11e87a7

Browse files
committed
Addressed PR review comments on liveobjects public API
- PathObjectSubscriptionOptions: validate depth fail-fast per RTPO19c1a, throwing AblyException with ErrorInfo(400, 40003) when depth <= 0. Depth is now a primitive int; the "no depth / infinite depth" state is expressed via a new no-arg constructor (mirrors ably-js `{}` options), so no null handling is needed - LiveMapValue: defensively copy binary payloads on creation and access, making the RTLMV3d immutability guarantee real for byte[] values - ObjectData#getBytes: document that the returned array is the underlying message payload and must be treated as read-only - JsonObjectPathObject/JsonArrayPathObject: reword "primitive resolution" javadoc for clarity - LiveMapPathObject#at: fix javadoc equivalence example to compile (get() returns base PathObject, so chain via asLiveMap())
1 parent 59a5ecc commit 11e87a7

6 files changed

Lines changed: 35 additions & 11 deletions

File tree

lib/src/main/java/io/ably/lib/object/message/ObjectData.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public interface ObjectData {
5151
@Nullable Boolean getBoolean();
5252

5353
/**
54-
* Returns the binary value.
54+
* Returns the binary value. The returned array is the underlying message
55+
* payload and is not defensively copied; callers must treat it as read-only.
5556
*
5657
* <p>Spec: OD2c
5758
*

lib/src/main/java/io/ably/lib/object/path/PathObjectSubscriptionOptions.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.ably.lib.object.path;
22

3+
import io.ably.lib.types.AblyException;
4+
import io.ably.lib.types.ErrorInfo;
35
import org.jetbrains.annotations.Nullable;
46

57
/**
@@ -13,12 +15,32 @@ public final class PathObjectSubscriptionOptions {
1315
private final Integer depth;
1416

1517
/**
16-
* Creates options with the given {@code depth}.
18+
* Creates options with no {@code depth} set: there is no depth limit, and
19+
* changes at any depth within nested children trigger the listener.
20+
* Equivalent to passing a {@code null} depth.
21+
*
22+
* <p>Spec: RTPO19c1
23+
*/
24+
public PathObjectSubscriptionOptions() {
25+
this.depth = null;
26+
}
27+
28+
/**
29+
* Creates options with the given {@code depth}. For infinite depth, use the
30+
* no-arg constructor {@link #PathObjectSubscriptionOptions()} instead.
31+
*
32+
* <p>Spec: RTPO19c1, RTPO19c1a
1733
*
1834
* @param depth how many levels of path nesting below the subscribed path should
19-
* trigger the listener; must be a positive integer if provided
35+
* trigger the listener; must be a positive integer
36+
* @throws AblyException with {@code statusCode} 400 and {@code code} 40003 if
37+
* {@code depth} is not a positive integer
2038
*/
21-
public PathObjectSubscriptionOptions(@Nullable Integer depth) {
39+
public PathObjectSubscriptionOptions(int depth) throws AblyException {
40+
if (depth <= 0) {
41+
throw AblyException.fromErrorInfo(
42+
new ErrorInfo("Subscription depth must be greater than 0 or omitted for infinite depth", 400, 40003));
43+
}
2244
this.depth = depth;
2345
}
2446

lib/src/main/java/io/ably/lib/object/path/types/JsonArrayPathObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* A {@link PathObject} whose underlying value is expected to be a {@link JsonArray}.
99
*
1010
* <p>This is a terminal type. {@link PathObject#instance()} returns {@code null}
11-
* because a primitive resolution does not produce a wrapped LiveObject; navigation
11+
* because this resolution does not produce a wrapped LiveObject instance; navigation
1212
* via {@code at(...)} is not available here because it is only defined on
1313
* {@code LiveMapPathObject}. Only {@link #value()} and the inherited read APIs are
1414
* useful here.

lib/src/main/java/io/ably/lib/object/path/types/JsonObjectPathObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* A {@link PathObject} whose underlying value is expected to be a {@link JsonObject}.
99
*
1010
* <p>This is a terminal type. {@link PathObject#instance()} returns {@code null}
11-
* because a primitive resolution does not produce a wrapped LiveObject; navigation
11+
* because this resolution does not produce a wrapped LiveObject instance; navigation
1212
* via {@code at(...)} is not available here because it is only defined on
1313
* {@code LiveMapPathObject}. Only {@link #value()} and the inherited read APIs are
1414
* useful here.

lib/src/main/java/io/ably/lib/object/path/types/LiveMapPathObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public interface LiveMapPathObject extends PathObject {
4646
*
4747
* <p>This is purely navigational - no resolution against the LiveObjects graph is
4848
* performed by this call. {@code liveMapPath.at("a.b.c")} is equivalent to
49-
* {@code liveMapPath.get("a").get("b").get("c")}.
49+
* {@code liveMapPath.get("a").asLiveMap().get("b").asLiveMap().get("c")}.
5050
*
5151
* <p>Available only on {@code LiveMapPathObject} because deeper navigation is only
5252
* meaningful when the current resolved value is a {@code LiveMap}. To traverse from

lib/src/main/java/io/ably/lib/object/value/LiveMapValue.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ public static LiveMapValue of(@NotNull Boolean value) {
183183
}
184184

185185
/**
186-
* Creates a LiveMapValue from a Binary.
186+
* Creates a LiveMapValue from a Binary. The array is copied, so later
187+
* modifications to {@code value} do not affect the created LiveMapValue.
187188
*
188189
* @param value the binary value
189190
* @return a LiveMapValue containing the binary
@@ -290,19 +291,19 @@ private static final class BinaryValue extends LiveMapValue {
290291
private final byte[] value;
291292

292293
BinaryValue(byte @NotNull [] value) {
293-
this.value = value;
294+
this.value = value.clone();
294295
}
295296

296297
@Override
297298
public @NotNull Object getValue() {
298-
return value;
299+
return value.clone();
299300
}
300301

301302
@Override
302303
public boolean isBinary() { return true; }
303304

304305
@Override
305-
public byte @NotNull [] getAsBinary() { return value; }
306+
public byte @NotNull [] getAsBinary() { return value.clone(); }
306307
}
307308

308309
/**

0 commit comments

Comments
 (0)