@Override
    public Either<L, R> copy(Either<L, R> from) {
        if (from.isLeft()) {
            L left = from.left();
            L copyLeft = leftSerializer.copy(left);
            return Left(copyLeft);
        } else {
            R right = from.right();
            R copyRight = rightSerializer.copy(right);
            return Right(copyRight);
        }
    }
@Test
    void testEitherWithObjectReuse() {
        EitherTypeInfo<LongValue, DoubleValue> eitherTypeInfo =
                new EitherTypeInfo<>(
                        ValueTypeInfo.LONG_VALUE_TYPE_INFO, ValueTypeInfo.DOUBLE_VALUE_TYPE_INFO);
        EitherSerializer<LongValue, DoubleValue> eitherSerializer =
                (EitherSerializer<LongValue, DoubleValue>)
                        eitherTypeInfo.createSerializer(new SerializerConfigImpl());

        LongValue lv = new LongValue();
        DoubleValue dv = new DoubleValue();

        Either<LongValue, DoubleValue> left = Left(lv);
        Either<LongValue, DoubleValue> right = Right(dv);

        // the first copy creates a new instance of Left
        Either<LongValue, DoubleValue> copy0 = eitherSerializer.copy(left, right);

        // then the cross-references are used for future copies
        Either<LongValue, DoubleValue> copy1 = eitherSerializer.copy(right, copy0);
        Either<LongValue, DoubleValue> copy2 = eitherSerializer.copy(left, copy1);

        // validate reference equality
        assertThat(copy1).isSameAs(right);
        assertThat(copy2).isSameAs(copy0);

        // validate reference equality of contained objects
        assertThat(copy1.right()).isSameAs(right.right());
        assertThat(copy2.left()).isSameAs(copy0.left());
    }