Skip to content
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

[Prework] Landing all 'conjure-lib' API changes Ahead of CodeGen Adoption #2417

Merged
merged 5 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public long longValue() {
return longValue;
}

private static long check(long value) {
public static long check(long value) {
bmarcaur marked this conversation as resolved.
Show resolved Hide resolved
Preconditions.checkArgument(
MIN_SAFE_VALUE <= value && value <= MAX_SAFE_VALUE,
"number must be safely representable in javascript i.e. "
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import com.palantir.conjure.java.lib.SafeLong;
import com.palantir.logsafe.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
Expand All @@ -37,6 +39,35 @@ private ConjureCollections() {
// cannot instantiate
}

/*
* This is bizarre. Allow me to explain...
*
* We do _not_ want to expose the Conjure*List types externally
* but we also want the optimizations they provide to make it thru
* to jackson for serialization. So the runtime type needs to be
* preserved while also not exposing the type :phew:.
*
* To achieve this we have to do some gymnastics surrounding the type
* system. We need this to return the type of the list given, but also
* return specific Conjure types when detected. This requires that we
* erase the type info, but we know this is safe because we are directly
* returning the same type which is by definition the identity function.
* Therefore the input List<T> is the same types as the output List<T>.
*/
public static <T> List<T> unmodifiableList(List<T> list) {
// Return the unmodifiable version of the Eclipse types
if (list instanceof ConjureIntegerList) {
return (List<T>) ((ConjureIntegerList) list).asUnmodifiable();
} else if (list instanceof ConjureDoubleList) {
return (List<T>) ((ConjureDoubleList) list).asUnmodifiable();
} else if (list instanceof ConjureSafeLongList) {
return (List<T>) ((ConjureSafeLongList) list).asUnmodifiable();
} else {
// Otherwise use the JDK types
return Collections.unmodifiableList(list);
}
bmarcaur marked this conversation as resolved.
Show resolved Hide resolved
}

@SuppressWarnings("unchecked")
public static <T> void addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) {
Preconditions.checkNotNull(elementsToAdd, "elementsToAdd cannot be null");
Expand Down Expand Up @@ -139,6 +170,12 @@ public static <T> Set<T> newNonNullSet(Iterable<? extends T> iterable) {
return set;
}

/**
* The following Conjure boxed list wrappers for the eclipse-collections [type]ArrayList are temporary (except
* ConjureSafeLongList). In eclipse-collections 12, a BoxedMutable[type]List will be released. Once available,
* Conjure[type]List should be replaced with that.
*/

// This method returns a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static List<Double> newNonNullDoubleList() {
return new ConjureDoubleList(new DoubleArrayList());
Expand All @@ -157,11 +194,14 @@ public static List<Double> newNonNullDoubleList(Iterable<Double> iterable) {
return doubleList;
}

/**
* The following Conjure boxed list wrappers for the eclipse-collections [type]ArrayList are temporary (except
* ConjureSafeLongList). In eclipse-collections 12, a BoxedMutable[type]List will be released. Once available,
* Conjure[type]List should be replaced with that.
*/
// This method modifies a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static void addAllToDoubleList(Collection<Double> addTo, double[] elementsToAdd) {
if (addTo instanceof ConjureDoubleList) {
((ConjureDoubleList) addTo).addAll(elementsToAdd);
} else {
addAll(addTo, () -> Arrays.stream(elementsToAdd).iterator());
}
}

// This method returns a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static List<Integer> newNonNullIntegerList() {
Expand All @@ -181,9 +221,19 @@ public static List<Integer> newNonNullIntegerList(Iterable<Integer> iterable) {
return integerList;
}

// This method modifies a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static void addAllToIntegerList(Collection<Integer> addTo, int[] elementsToAdd) {
if (addTo instanceof ConjureIntegerList) {
((ConjureIntegerList) addTo).addAll(elementsToAdd);
} else {
addAll(addTo, () -> Arrays.stream(elementsToAdd).iterator());
}
}

/**
* Deprecated, this should only ever be called by a previously generated conjure internal implementation.
*/
// This method returns a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static List<Boolean> newNonNullBooleanList() {
return newNonNullList();
}
Expand Down Expand Up @@ -212,4 +262,13 @@ public static List<SafeLong> newNonNullSafeLongList(Iterable<SafeLong> iterable)

return safeLongList;
}

// This method modifies a list that can't handle nulls. Do not use this unless the nonNullCollections flag is set
public static void addAllToSafeLongList(Collection<SafeLong> addTo, long[] elementsToAdd) {
if (addTo instanceof ConjureSafeLongList) {
((ConjureSafeLongList) addTo).addAll(elementsToAdd);
} else {
addAll(addTo, Arrays.stream(elementsToAdd).boxed().map(SafeLong::of).toList());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.annotation.JsonValue;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
import org.eclipse.collections.impl.list.mutable.primitive.DoubleArrayList;
import org.eclipse.collections.api.list.primitive.MutableDoubleList;
import org.eclipse.collections.impl.utility.Iterate;

/**
* ConjureDoubleList is a boxed list wrapper for the eclipse-collections DoubleArrayList. In eclipse-collections 12,
* a BoxedMutableDoubleList will be released. Once available, ConjureDoubleList should be replaced with that.
*/
final class ConjureDoubleList extends AbstractList<Double> implements RandomAccess {
private final DoubleArrayList delegate;
private final MutableDoubleList delegate;

ConjureDoubleList(DoubleArrayList delegate) {
ConjureDoubleList(MutableDoubleList delegate) {
this.delegate = delegate;
}

Expand All @@ -55,6 +56,10 @@ public boolean addAll(int index, Collection<? extends Double> collection) {
return delegate.addAllAtIndex(index, target);
}

public void addAll(double... source) {
this.delegate.addAll(source);
}

@Override
public Double remove(int index) {
return delegate.removeAtIndex(index);
Expand All @@ -69,4 +74,15 @@ public void clear() {
public Double set(int index, Double element) {
return delegate.set(index, element);
}

public ConjureDoubleList asUnmodifiable() {
return new ConjureDoubleList(delegate.asUnmodifiable());
}

// Cannot be named 'toArray' as that conflicts with the #toArray in AbstractList
// This is a serialization optimization that avoids boxing, but does copy
@JsonValue
double[] jacksonSerialize() {
return delegate.toArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,21 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.annotation.JsonValue;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
import org.eclipse.collections.impl.list.mutable.primitive.IntArrayList;
import org.eclipse.collections.api.list.primitive.MutableIntList;
import org.eclipse.collections.impl.utility.Iterate;

/**
* ConjureIntegerList is a boxed list wrapper for the eclipse-collections IntArrayList. In eclipse-collections 12,
* a BoxedMutableIntList will be released. Once available, ConjureIntegerList should be replaced with that.
*/
final class ConjureIntegerList extends AbstractList<Integer> implements RandomAccess {
private final IntArrayList delegate;
private final MutableIntList delegate;

ConjureIntegerList(IntArrayList delegate) {
ConjureIntegerList(MutableIntList delegate) {
this.delegate = delegate;
}

Expand All @@ -55,6 +56,10 @@ public boolean addAll(int index, Collection<? extends Integer> collection) {
return delegate.addAllAtIndex(index, target);
}

public void addAll(int... source) {
this.delegate.addAll(source);
}

@Override
public Integer remove(int index) {
return delegate.removeAtIndex(index);
Expand All @@ -69,4 +74,15 @@ public void clear() {
public Integer set(int index, Integer element) {
return delegate.set(index, element);
}

public ConjureIntegerList asUnmodifiable() {
return new ConjureIntegerList(delegate.asUnmodifiable());
}

// Cannot be named 'toArray' as that conflicts with the #toArray in AbstractList
// This is a serialization optimization that avoids boxing, but does copy
@JsonValue
int[] jacksonSerialize() {
return delegate.toArray();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@

package com.palantir.conjure.java.lib.internal;

import com.fasterxml.jackson.annotation.JsonValue;
import com.palantir.conjure.java.lib.SafeLong;
import java.util.AbstractList;
import java.util.Collection;
import java.util.RandomAccess;
import org.eclipse.collections.impl.list.mutable.primitive.LongArrayList;
import org.eclipse.collections.api.list.primitive.MutableLongList;
import org.eclipse.collections.impl.utility.Iterate;

/**
* ConjureSafeLongList is a boxed list wrapper for the eclipse-collections LongArrayList. This handles boxing/unboxing
* with SafeLongs.
*/
final class ConjureSafeLongList extends AbstractList<SafeLong> implements RandomAccess {
private final LongArrayList delegate;
private final MutableLongList delegate;

ConjureSafeLongList(LongArrayList delegate) {
ConjureSafeLongList(MutableLongList delegate) {
this.delegate = delegate;
}

Expand All @@ -56,6 +57,14 @@ public boolean addAll(int index, Collection<? extends SafeLong> collection) {
return delegate.addAllAtIndex(index, target);
}

public void addAll(long... source) {
for (long value : source) {
// Doesn't use SafeLong creation because this causes unnecessary boxing
SafeLong.check(value);
}
this.delegate.addAll(source);
}

@Override
public SafeLong remove(int index) {
return SafeLong.of(delegate.removeAtIndex(index));
Expand All @@ -70,4 +79,15 @@ public void clear() {
public SafeLong set(int index, SafeLong element) {
return SafeLong.of(delegate.set(index, element.longValue()));
}

public ConjureSafeLongList asUnmodifiable() {
return new ConjureSafeLongList(delegate.asUnmodifiable());
}

// Cannot be named 'toArray' as that conflicts with the #toArray in AbstractList
// This is a serialization optimization that avoids boxing, but does copy
@JsonValue
long[] jacksonSerialize() {
return delegate.toArray();
}
}