Skip to content

Commit

Permalink
feat: provide inefficient AString reducers
Browse files Browse the repository at this point in the history
  • Loading branch information
tynn committed Dec 30, 2023
1 parent 91334ff commit 821ca1e
Show file tree
Hide file tree
Showing 20 changed files with 1,912 additions and 80 deletions.
28 changes: 24 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,38 @@ and equivalents for `getQuantityString()` and `getQuantityText()` provided by
QuantityStringResource(R.plurals.res_id, 1, "arg")
QuantityTextResource(R.plurals.res_id, 2)

While `AppId` or `AppVersion` just provide data from the `Context` itself.
While `AppId` or `AppVersion` just provide the data from the `Context` itself.

### `AString` Transformers

While `AString` represent any generic `CharSequence`, it might be useful to
transform the value before its use.
Since the `AString` represent any generic `CharSequence`, it might be useful
to transform the value before its use.

aString.format("arg", AppId)
aString.defaultIfNull("value")
aString.nullIfBlank()
aString.string()
aString.mapToString()
aString.trim()

### `AString` Reducers

If multiple instances of `AString` are provided, it is also possible to reduce
these to a single and single `AString`.

aStrings.firstNonBlank()
aStrings.joinNonNull(',')

The provided values of the `Iterable` are provided lazily.

### `@InefficientAStringApi AString` usages

Generic `AString.Provider`, `AString.Transformer` and `AString.Reducer` are
supported but do not provide comparability or readable string representations.

AString { it.packageName }
aString.map { it?.toString() }
aStrings.reduce { it.singleOrNull() }

### _Jetpack_ Compose extension functions
[![API][compose-shield]][compose]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright 2023 Christian Schmitz
// SPDX-License-Identifier: Apache-2.0

package xyz.tynn.astring;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static xyz.tynn.astring.AStringFactory.createFromCharSequence;
import static xyz.tynn.astring.test.AStringAssert.assertParcelableAStringInvocation;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.junit.Test;

import java.util.List;

public class AStringReducerAndroidTest {

private final Iterable<AString> aStrings = List.of(AString.Null);

@Test
public void delegate_should_implement_parcelable() {
String value = "value";
assertParcelableAStringInvocation(Delegate.wrap($ -> value, aStrings));
assertParcelableAStringInvocation(Delegate.wrap($ -> value,
AString.Null, createFromCharSequence("value")));
}

@Test
@SuppressWarnings("Convert2Lambda")
public void interface_should_not_be_efficient() {
assertNotEquals(AStringFactory.reduce(aStrings, new AString.Reducer() {
@Override
public CharSequence invoke(@NonNull Iterable<? extends CharSequence> values) {
return "";
}
}), AStringFactory.reduce(aStrings, new AString.Reducer() {
@Override
public CharSequence invoke(@NonNull Iterable<? extends CharSequence> values) {
return "";
}
}));
}

@Test
@SuppressWarnings("Convert2Lambda")
public void interface_ref_should_be_efficient() {
AString.Reducer function = new AString.Reducer() {
@Override
public CharSequence invoke(@NonNull Iterable<? extends CharSequence> values) {
return "";
}
};
assertEquals(AStringFactory.reduce(aStrings, function),
AStringFactory.reduce(aStrings, function));
}

@Test
public void instance_should_be_efficient() {
assertEquals(AStringFactory.reduce(aStrings, new Reducer()),
AStringFactory.reduce(aStrings, new Reducer()));
}

@Test
public void instance_ref_should_be_efficient() {
AString.Reducer function = new Reducer();
assertEquals(AStringFactory.reduce(aStrings, function),
AStringFactory.reduce(aStrings, function));
}

@Test
public void function_should_not_be_efficient() {
assertNotEquals(AStringFactory.reduce(aStrings, this::function),
AStringFactory.reduce(aStrings, this::function));
}

@Test
public void function_ref_should_be_efficient() {
AString.Reducer function = this::function;
assertEquals(AStringFactory.reduce(aStrings, function),
AStringFactory.reduce(aStrings, function));
}

@Test
public void lambda_should_not_be_efficient() {
assertNotEquals(AStringFactory.reduce(aStrings, values -> ""),
AStringFactory.reduce(aStrings, values -> ""));
}

@Test
public void lambda_ref_should_be_efficient() {
AString.Reducer function = values -> "";
assertEquals(AStringFactory.reduce(aStrings, function),
AStringFactory.reduce(aStrings, function));
}

private CharSequence function(Iterable<? extends CharSequence> values) {
return "";
}

private final static class Reducer implements AString.Reducer {

@Nullable
@Override
public CharSequence invoke(@NonNull Iterable<? extends CharSequence> values) {
return null;
}

@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof Reducer;
}

@Override
public int hashCode() {
return 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,18 @@ public void Delegate_should_implement_parcelable() {
assertParcelableAStringEquality(Delegate.wrap(Provider.AppVersion));
assertParcelableAStringInvocation(Delegate.wrap(Provider.AppVersion));
assertParcelableAStringInvocation(Delegate.wrap(Object::toString));
assertParcelableAStringIdentity(Delegate.wrap(null, null));
assertParcelableAStringInvocation(Delegate.wrap(null, null));
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonBlank, FORMAT));
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonBlank, FORMAT));
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonEmpty, FORMAT));
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonEmpty, FORMAT));
assertParcelableAStringEquality(Delegate.wrap(Predicate.NonNull, FORMAT));
assertParcelableAStringInvocation(Delegate.wrap(Predicate.NonNull, FORMAT));
assertParcelableAStringEquality(Delegate.wrap(Transformer.ToString, FORMAT));
assertParcelableAStringInvocation(Delegate.wrap(Transformer.ToString, FORMAT));
assertParcelableAStringEquality(Delegate.wrap(Transformer.Trim, FORMAT));
assertParcelableAStringInvocation(Delegate.wrap(Transformer.Trim, FORMAT));
assertParcelableAStringIdentity(Delegate.wrap((AString) null, null));
assertParcelableAStringInvocation(Delegate.wrap((AString) null, null));
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonBlank));
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonBlank));
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonEmpty));
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonEmpty));
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Predicate.NonNull));
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Predicate.NonNull));
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Transformer.ToString));
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Transformer.ToString));
assertParcelableAStringEquality(Delegate.wrap(FORMAT, Transformer.Trim));
assertParcelableAStringInvocation(Delegate.wrap(FORMAT, Transformer.Trim));
}

private static class FormatAString implements AString {
Expand Down
Loading

0 comments on commit 821ca1e

Please sign in to comment.