package net.minecraft.network.codec; import com.google.common.base.Suppliers; import com.mojang.datafixers.util.Function10; import com.mojang.datafixers.util.Function11; import com.mojang.datafixers.util.Function12; import com.mojang.datafixers.util.Function3; import com.mojang.datafixers.util.Function4; import com.mojang.datafixers.util.Function5; import com.mojang.datafixers.util.Function6; import com.mojang.datafixers.util.Function7; import com.mojang.datafixers.util.Function8; import com.mojang.datafixers.util.Function9; import io.netty.buffer.ByteBuf; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.function.UnaryOperator; public interface StreamCodec extends StreamEncoder, StreamDecoder { static StreamCodec of(final StreamEncoder encoder, final StreamDecoder decoder) { return new StreamCodec() { @Override public V decode(final B input) { return decoder.decode(input); } @Override public void encode(final B output, final V value) { encoder.encode(output, value); } }; } static StreamCodec ofMember(final StreamMemberEncoder encoder, final StreamDecoder decoder) { return new StreamCodec() { @Override public V decode(final B input) { return decoder.decode(input); } @Override public void encode(final B output, final V value) { encoder.encode(value, output); } }; } static StreamCodec unit(final V instance) { return new StreamCodec() { @Override public V decode(final B input) { return instance; } @Override public void encode(final B output, final V value) { if (!value.equals(instance)) { throw new IllegalStateException("Can't encode '" + value + "', expected '" + instance + "'"); } } }; } default StreamCodec apply(final StreamCodec.CodecOperation operation) { return operation.apply(this); } default StreamCodec map(final Function to, final Function from) { return new StreamCodec() { { Objects.requireNonNull(StreamCodec.this); } @Override public O decode(final B input) { return (O)to.apply(StreamCodec.this.decode(input)); } @Override public void encode(final B output, final O value) { StreamCodec.this.encode(output, (V)from.apply(value)); } }; } default StreamCodec mapStream(final Function operation) { return new StreamCodec() { { Objects.requireNonNull(StreamCodec.this); } public V decode(final O input) { B wrappedStream = (B)operation.apply(input); return StreamCodec.this.decode(wrappedStream); } public void encode(final O output, final V value) { B wrappedStream = (B)operation.apply(output); StreamCodec.this.encode(wrappedStream, value); } }; } default StreamCodec dispatch( final Function type, final Function> codec ) { return new StreamCodec() { { Objects.requireNonNull(StreamCodec.this); } @Override public U decode(final B input) { V key = StreamCodec.this.decode(input); StreamCodec valueCodec = (StreamCodec)codec.apply(key); return (U)valueCodec.decode(input); } @Override public void encode(final B output, final U value) { V key = (V)type.apply(value); StreamCodec valueCodec = (StreamCodec)codec.apply(key); StreamCodec.this.encode(output, key); valueCodec.encode(output, value); } }; } static StreamCodec composite(final StreamCodec codec1, final Function getter1, final Function constructor) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); return (C)constructor.apply(v1); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final BiFunction constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); return (C)constructor.apply(v1, v2); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final Function3 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); return constructor.apply(v1, v2, v3); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final Function4 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); return constructor.apply(v1, v2, v3, v4); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final Function5 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); return constructor.apply(v1, v2, v3, v4, v5); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final Function6 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final Function7 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final StreamCodec codec8, final Function getter8, final Function8 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); T8 v8 = codec8.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7, v8); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); codec8.encode(output, (T8)getter8.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final StreamCodec codec8, final Function getter8, final StreamCodec codec9, final Function getter9, final Function9 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); T8 v8 = codec8.decode(input); T9 v9 = codec9.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7, v8, v9); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); codec8.encode(output, (T8)getter8.apply(value)); codec9.encode(output, (T9)getter9.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final StreamCodec codec8, final Function getter8, final StreamCodec codec9, final Function getter9, final StreamCodec codec10, final Function getter10, final Function10 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); T8 v8 = codec8.decode(input); T9 v9 = codec9.decode(input); T10 v10 = codec10.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); codec8.encode(output, (T8)getter8.apply(value)); codec9.encode(output, (T9)getter9.apply(value)); codec10.encode(output, (T10)getter10.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final StreamCodec codec8, final Function getter8, final StreamCodec codec9, final Function getter9, final StreamCodec codec10, final Function getter10, final StreamCodec codec11, final Function getter11, final Function11 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); T8 v8 = codec8.decode(input); T9 v9 = codec9.decode(input); T10 v10 = codec10.decode(input); T11 v11 = codec11.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); codec8.encode(output, (T8)getter8.apply(value)); codec9.encode(output, (T9)getter9.apply(value)); codec10.encode(output, (T10)getter10.apply(value)); codec11.encode(output, (T11)getter11.apply(value)); } }; } static StreamCodec composite( final StreamCodec codec1, final Function getter1, final StreamCodec codec2, final Function getter2, final StreamCodec codec3, final Function getter3, final StreamCodec codec4, final Function getter4, final StreamCodec codec5, final Function getter5, final StreamCodec codec6, final Function getter6, final StreamCodec codec7, final Function getter7, final StreamCodec codec8, final Function getter8, final StreamCodec codec9, final Function getter9, final StreamCodec codec10, final Function getter10, final StreamCodec codec11, final Function getter11, final StreamCodec codec12, final Function getter12, final Function12 constructor ) { return new StreamCodec() { @Override public C decode(final B input) { T1 v1 = codec1.decode(input); T2 v2 = codec2.decode(input); T3 v3 = codec3.decode(input); T4 v4 = codec4.decode(input); T5 v5 = codec5.decode(input); T6 v6 = codec6.decode(input); T7 v7 = codec7.decode(input); T8 v8 = codec8.decode(input); T9 v9 = codec9.decode(input); T10 v10 = codec10.decode(input); T11 v11 = codec11.decode(input); T12 v12 = codec12.decode(input); return constructor.apply(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12); } @Override public void encode(final B output, final C value) { codec1.encode(output, (T1)getter1.apply(value)); codec2.encode(output, (T2)getter2.apply(value)); codec3.encode(output, (T3)getter3.apply(value)); codec4.encode(output, (T4)getter4.apply(value)); codec5.encode(output, (T5)getter5.apply(value)); codec6.encode(output, (T6)getter6.apply(value)); codec7.encode(output, (T7)getter7.apply(value)); codec8.encode(output, (T8)getter8.apply(value)); codec9.encode(output, (T9)getter9.apply(value)); codec10.encode(output, (T10)getter10.apply(value)); codec11.encode(output, (T11)getter11.apply(value)); codec12.encode(output, (T12)getter12.apply(value)); } }; } static StreamCodec recursive(final UnaryOperator> factory) { return new StreamCodec() { private final Supplier> inner = Suppliers.memoize(() -> (StreamCodec)factory.apply(this)); @Override public T decode(final B input) { return (T)((StreamCodec)this.inner.get()).decode(input); } @Override public void encode(final B output, final T value) { ((StreamCodec)this.inner.get()).encode(output, (V)value); } }; } default StreamCodec cast() { return this; } @FunctionalInterface public interface CodecOperation { StreamCodec apply(StreamCodec original); } }