diff --git a/pom.xml b/pom.xml index 735ed44..908f29d 100644 --- a/pom.xml +++ b/pom.xml @@ -17,7 +17,7 @@ io.vavr vavr - 0.10.4 + 0.10.4 diff --git a/src/main/java/com/utp/Traits/FromStr.java b/src/main/java/com/utp/Traits/FromStr.java deleted file mode 100644 index bf493ed..0000000 --- a/src/main/java/com/utp/Traits/FromStr.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.utp.Traits; - -import io.vavr.control.Validation; - -public interface FromStr { - public Validation from_str(String input); -} diff --git a/src/main/java/com/utp/io_vavrs/Validation.java b/src/main/java/com/utp/io_vavrs/Validation.java new file mode 100644 index 0000000..89ae9f0 --- /dev/null +++ b/src/main/java/com/utp/io_vavrs/Validation.java @@ -0,0 +1,819 @@ +package com.utp.io_vavrs; + +/* __ __ __ __ __ ___ + * \ \ / / \ \ / / __/ + * \ \/ / /\ \ \/ / / + * \____/__/ \__\____/__/ + * + * Copyright 2014-2021 Vavr, http://vavr.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.Serializable; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; + +/** + * An implementation similar to scalaz's Validation control. + * + *

+ * The Validation type is different from a Monad type, it is an applicative + * functor. Whereas a Monad will short circuit after the first error, the + * applicative functor will continue on, accumulating ALL errors. This is + * especially helpful in cases such as validation, where you want to know + * all the validation errors that have occurred, not just the first one. + *

+ * + *
+ * 
+ * Validation construction:
+ *
+ * Valid:
+ * Validation<String,Integer> valid = Validation.valid(5);
+ *
+ * Invalid:
+ * Validation<List<String>,Integer> invalid = Validation.invalid(List.of("error1","error2"));
+ *
+ * Validation combination:
+ *
+ * Validation<String,String> valid1 = Validation.valid("John");
+ * Validation<String,Integer> valid2 = Validation.valid(5);
+ * Validation<String,Option<String>> valid3 = Validation.valid(Option.of("123 Fake St."));
+ * Function3<String,Integer,Option<String>,Person> f = ...;
+ *
+ * Validation<List<String>,String> result = valid1.combine(valid2).ap((name,age) -> "Name: "+name+" Age: "+age);
+ * Validation<List<String>,Person> result2 = valid1.combine(valid2).combine(valid3).ap(f);
+ *
+ * Another form of combining validations:
+ *
+ * Validation<List<String>,Person> result3 = Validation.combine(valid1, valid2, valid3).ap(f);
+ * 
+ * 
+ * + * @param value type in the case of invalid + * @param value type in the case of valid + * @author Eric Nelson + * @see Validation + */ +public interface Validation extends Serializable { + + long serialVersionUID = 1L; + + /** + * Creates a {@link Valid} that contains the given {@code value}. + * + * @param type of the error + * @param type of the given {@code value} + * @param value A value + * @return {@code Valid(value)} + */ + static Validation valid(T value) { + return new Valid<>(value); + } + + /** + * Creates an {@link Invalid} that contains the given {@code error}. + * + * @param type of the given {@code error} + * @param type of the value + * @param error An error + * @return {@code Invalid(error)} + * @throws NullPointerException if error is null + */ + static Validation invalid(E error) { + Objects.requireNonNull(error, "error is null"); + return new Invalid<>(error); + } + + /** + * Narrows a widened {@code Validation} to {@code Validation} + * by performing a type-safe cast. This is eligible because immutable/read-only + * collections are covariant. + * + * @param validation A {@code Validation}. + * @param type of error + * @param type of valid value + * @return the given {@code validation} instance as narrowed type {@code Validation}. + */ + @SuppressWarnings("unchecked") + static Validation narrow(Validation validation) { + return (Validation) validation; + } + + /** + * Combines two {@code Validation}s into a {@link Builder}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param validation1 first validation + * @param validation2 second validation + * @return an instance of Builder<E,T1,T2> + * @throws NullPointerException if validation1 or validation2 is null + */ + static Builder combine(Validation validation1, Validation validation2) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + return new Builder<>(validation1, validation2); + } + + /** + * Combines three {@code Validation}s into a {@link Builder3}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @return an instance of Builder3<E,T1,T2,T3> + * @throws NullPointerException if validation1, validation2 or validation3 is null + */ + static Builder3 combine(Validation validation1, Validation validation2, Validation validation3) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + return new Builder3<>(validation1, validation2, validation3); + } + + /** + * Combines four {@code Validation}s into a {@link Builder4}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param type of fourth valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @param validation4 fourth validation + * @return an instance of Builder3<E,T1,T2,T3,T4> + * @throws NullPointerException if validation1, validation2, validation3 or validation4 is null + */ + static Builder4 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + Objects.requireNonNull(validation4, "validation4 is null"); + return new Builder4<>(validation1, validation2, validation3, validation4); + } + + /** + * Combines five {@code Validation}s into a {@link Builder5}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param type of fourth valid value + * @param type of fifth valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @param validation4 fourth validation + * @param validation5 fifth validation + * @return an instance of Builder3<E,T1,T2,T3,T4,T5> + * @throws NullPointerException if validation1, validation2, validation3, validation4 or validation5 is null + */ + static Builder5 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + Objects.requireNonNull(validation4, "validation4 is null"); + Objects.requireNonNull(validation5, "validation5 is null"); + return new Builder5<>(validation1, validation2, validation3, validation4, validation5); + } + + /** + * Combines six {@code Validation}s into a {@link Builder6}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param type of fourth valid value + * @param type of fifth valid value + * @param type of sixth valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @param validation4 fourth validation + * @param validation5 fifth validation + * @param validation6 sixth validation + * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6> + * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5 or validation6 is null + */ + static Builder6 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + Objects.requireNonNull(validation4, "validation4 is null"); + Objects.requireNonNull(validation5, "validation5 is null"); + Objects.requireNonNull(validation6, "validation6 is null"); + return new Builder6<>(validation1, validation2, validation3, validation4, validation5, validation6); + } + + /** + * Combines seven {@code Validation}s into a {@link Builder7}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param type of fourth valid value + * @param type of fifth valid value + * @param type of sixth valid value + * @param type of seventh valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @param validation4 fourth validation + * @param validation5 fifth validation + * @param validation6 sixth validation + * @param validation7 seventh validation + * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7> + * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6 or validation7 is null + */ + static Builder7 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6, Validation validation7) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + Objects.requireNonNull(validation4, "validation4 is null"); + Objects.requireNonNull(validation5, "validation5 is null"); + Objects.requireNonNull(validation6, "validation6 is null"); + Objects.requireNonNull(validation7, "validation7 is null"); + return new Builder7<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7); + } + + /** + * Combines eight {@code Validation}s into a {@link Builder8}. + * + * @param type of error + * @param type of first valid value + * @param type of second valid value + * @param type of third valid value + * @param type of fourth valid value + * @param type of fifth valid value + * @param type of sixth valid value + * @param type of seventh valid value + * @param type of eighth valid value + * @param validation1 first validation + * @param validation2 second validation + * @param validation3 third validation + * @param validation4 fourth validation + * @param validation5 fifth validation + * @param validation6 sixth validation + * @param validation7 seventh validation + * @param validation8 eighth validation + * @return an instance of Builder3<E,T1,T2,T3,T4,T5,T6,T7,T8> + * @throws NullPointerException if validation1, validation2, validation3, validation4, validation5, validation6, validation7 or validation8 is null + */ + static Builder8 combine(Validation validation1, Validation validation2, Validation validation3, Validation validation4, Validation validation5, Validation validation6, Validation validation7, Validation validation8) { + Objects.requireNonNull(validation1, "validation1 is null"); + Objects.requireNonNull(validation2, "validation2 is null"); + Objects.requireNonNull(validation3, "validation3 is null"); + Objects.requireNonNull(validation4, "validation4 is null"); + Objects.requireNonNull(validation5, "validation5 is null"); + Objects.requireNonNull(validation6, "validation6 is null"); + Objects.requireNonNull(validation7, "validation7 is null"); + Objects.requireNonNull(validation8, "validation8 is null"); + return new Builder8<>(validation1, validation2, validation3, validation4, validation5, validation6, validation7, validation8); + } + + /** + * Check whether this is of type {@code Valid} + * + * @return true if is a Valid, false if is an Invalid + */ + boolean isValid(); + + /** + * Check whether this is of type {@code Invalid} + * + * @return true if is an Invalid, false if is a Valid + */ + boolean isInvalid(); + + /** + * Returns this {@code Validation} if it is valid, otherwise return the alternative. + * + * @param other An alternative {@code Validation} + * @return this {@code Validation} if it is valid, otherwise return the alternative. + */ + @SuppressWarnings("unchecked") + default Validation orElse(Validation other) { + Objects.requireNonNull(other, "other is null"); + return isValid() ? this : (Validation) other; + } + + /** + * Returns this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. + * + * @param supplier An alternative {@code Validation} supplier + * @return this {@code Validation} if it is valid, otherwise return the result of evaluating supplier. + */ + @SuppressWarnings("unchecked") + default Validation orElse(Supplier> supplier) { + Objects.requireNonNull(supplier, "supplier is null"); + return isValid() ? this : (Validation) supplier.get(); + } + + default boolean isEmpty() { + return isInvalid(); + } + + /** + * Gets the value of this {@code Validation} if is a {@code Valid} or throws if this is an {@code Invalid}. + * + * @return The value of this {@code Validation} + * @throws NoSuchElementException if this is an {@code Invalid} + */ + T get(); + + /** + * Gets the value if it is a Valid or an value calculated from the error. + * + * @param other a function which converts an error to an alternative value + * @return the value, if the underlying Validation is a Valid, or else the alternative value + * provided by {@code other} by applying the error. + */ + default T getOrElseGet(Function other) { + Objects.requireNonNull(other, "other is null"); + if (isValid()) { + return get(); + } else { + return other.apply(getError()); + } + } + + /** + * Gets the error of this Validation if it is an {@code Invalid} or throws if this is a {@code Valid}. + * + * @return The error, if present + * @throws RuntimeException if this is a {@code Valid} + */ + E getError(); + + @Override + boolean equals(Object o); + + @Override + int hashCode(); + + @Override + String toString(); + + /** + * Performs the given action for the value contained in {@code Valid}, or does nothing + * if this is an {@code Invalid}. + * + * @param action the action to be performed on the contained value + * @throws NullPointerException if action is null + */ + default void forEach(Consumer action) { + Objects.requireNonNull(action, "action is null"); + if (isValid()) { + action.accept(get()); + } + } + + /** + * Transforms this {@code Validation} to a value of type {@code U}. + *

+ * Example: + *

{@code
+     * Validation, String> valid = ...;
+ * int i = valid.fold(List::length, String::length); + * }
+ * + * @param the fold result type + * @param ifInvalid an error mapper + * @param ifValid an mapper for a valid value + * @return {@code ifValid.apply(get())} if this is valid, otherwise {@code ifInvalid.apply(getError())}. + * @throws NullPointerException if one of the given mappers {@code ifInvalid} or {@code ifValid} is null + */ + default U fold(Function ifInvalid, Function ifValid) { + Objects.requireNonNull(ifInvalid, "ifInvalid is null"); + Objects.requireNonNull(ifValid, "ifValid is null"); + return isValid() ? ifValid.apply(get()) : ifInvalid.apply(getError()); + } + + /** + * Flip the valid/invalid values for this Validation. If this is a Valid<E,T>, returns Invalid<T,E>. + * Or if this is an Invalid<E,T>, return a Valid<T,E>. + * + * @return a flipped instance of Validation + */ + default Validation swap() { + if (isInvalid()) { + final E error = this.getError(); + return Validation.valid(error); + } else { + final T value = this.get(); + return Validation.invalid(value); + } + } + + default Validation map(Function f) { + Objects.requireNonNull(f, "f is null"); + if (isInvalid()) { + return Validation.invalid(this.getError()); + } else { + final T value = this.get(); + return Validation.valid(f.apply(value)); + } + } + + /** + * Whereas map only performs a mapping on a valid Validation, and mapError performs a mapping on an invalid + * Validation, bimap allows you to provide mapping actions for both, and will give you the result based + * on what type of Validation this is. Without this, you would have to do something like: + * + * validation.map(...).mapError(...); + * + * @param type of the mapping result if this is an invalid + * @param type of the mapping result if this is a valid + * @param errorMapper the invalid mapping operation + * @param valueMapper the valid mapping operation + * @return an instance of Validation<U,R> + * @throws NullPointerException if invalidMapper or validMapper is null + */ + default Validation bimap(Function errorMapper, Function valueMapper) { + Objects.requireNonNull(errorMapper, "errorMapper is null"); + Objects.requireNonNull(valueMapper, "valueMapper is null"); + if (isInvalid()) { + final E error = this.getError(); + return Validation.invalid(errorMapper.apply(error)); + } else { + final T value = this.get(); + return Validation.valid(valueMapper.apply(value)); + } + } + + /** + * Applies a function f to the error of this Validation if this is an Invalid. Otherwise does nothing + * if this is a Valid. + * + * @param type of the error resulting from the mapping + * @param f a function that maps the error in this Invalid + * @return an instance of Validation<U,T> + * @throws NullPointerException if mapping operation f is null + */ + default Validation mapError(Function f) { + Objects.requireNonNull(f, "f is null"); + if (isInvalid()) { + final E error = this.getError(); + return Validation.invalid(f.apply(error)); + } else { + return Validation.valid(this.get()); + } + } + + /** + * Combines two {@code Validation}s to form a {@link Builder}, which can then be used to perform further + * combines, or apply a function to it in order to transform the {@link Builder} into a {@code Validation}. + * + * @param type of the value contained in validation + * @param validation the validation object to combine this with + * @return an instance of Builder + */ + default Builder combine(Validation validation) { + return new Builder<>(this, validation); + } + + // -- Implementation of Value + + default Optional> filter(Predicate predicate) { + Objects.requireNonNull(predicate, "predicate is null"); + return isInvalid() || predicate.test(get()) ? Optional.of(this) : Optional.empty(); + } + + @SuppressWarnings("unchecked") + default Validation flatMap(Function> mapper) { + Objects.requireNonNull(mapper, "mapper is null"); + return isInvalid() ? (Validation) this : (Validation) mapper.apply(get()); + } + + default Validation peek(Consumer action) { + if (isValid()) { + action.accept(get()); + } + return this; + } + + /** + * A {@code Validation}'s value is computed synchronously. + * + * @return false + */ + default boolean isAsync() { + return false; + } + + /** + * A {@code Validation}'s value is computed eagerly. + * + * @return false + */ + default boolean isLazy() { + return false; + } + + default boolean isSingleValued() { + return true; + } + + /** + * A valid Validation + * + * @param type of the error of this Validation + * @param type of the value of this Validation + */ + final class Valid implements Validation { + + private static final long serialVersionUID = 1L; + + private final T value; + + /** + * Construct a {@code Valid} + * + * @param value The value of this success + */ + private Valid(T value) { + this.value = value; + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public boolean isInvalid() { + return false; + } + + @Override + public T get() { + return value; + } + + @Override + public E getError() throws RuntimeException { + throw new NoSuchElementException("error of 'valid' Validation"); + } + + @Override + public boolean equals(Object obj) { + return (obj == this) || (obj instanceof Valid && Objects.equals(value, ((Valid) obj).value)); + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } + + public String stringPrefix() { + return "Valid"; + } + + @Override + public String toString() { + return stringPrefix() + "(" + value + ")"; + } + + } + + /** + * An invalid Validation + * + * @param type of the error of this Validation + * @param type of the value of this Validation + */ + final class Invalid implements Validation { + + private static final long serialVersionUID = 1L; + + private final E error; + + /** + * Construct an {@code Invalid} + * + * @param error The value of this error + */ + private Invalid(E error) { + this.error = error; + } + + @Override + public boolean isValid() { + return false; + } + + @Override + public boolean isInvalid() { + return true; + } + + @Override + public T get() throws RuntimeException { + throw new NoSuchElementException("get of 'invalid' Validation"); + } + + @Override + public E getError() { + return error; + } + + @Override + public boolean equals(Object obj) { + return (obj == this) || (obj instanceof Invalid && Objects.equals(error, ((Invalid) obj).error)); + } + + @Override + public int hashCode() { + return Objects.hashCode(error); + } + + public String stringPrefix() { + return "Invalid"; + } + + @Override + public String toString() { + return stringPrefix() + "(" + error + ")"; + } + + } + + final class Builder { + + private Validation v1; + private Validation v2; + + private Builder(Validation v1, Validation v2) { + this.v1 = v1; + this.v2 = v2; + } + + public Builder3 combine(Validation v3) { + return new Builder3<>(v1, v2, v3); + } + + } + + final class Builder3 { + + private Validation v1; + private Validation v2; + private Validation v3; + + private Builder3(Validation v1, Validation v2, Validation v3) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + } + + + public Builder4 combine(Validation v4) { + return new Builder4<>(v1, v2, v3, v4); + } + + } + + final class Builder4 { + + private Validation v1; + private Validation v2; + private Validation v3; + private Validation v4; + + private Builder4(Validation v1, Validation v2, Validation v3, Validation v4) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + } + + public Builder5 combine(Validation v5) { + return new Builder5<>(v1, v2, v3, v4, v5); + } + + } + + final class Builder5 { + + private Validation v1; + private Validation v2; + private Validation v3; + private Validation v4; + private Validation v5; + + private Builder5(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + } + + public Builder6 combine(Validation v6) { + return new Builder6<>(v1, v2, v3, v4, v5, v6); + } + + } + + final class Builder6 { + + private Validation v1; + private Validation v2; + private Validation v3; + private Validation v4; + private Validation v5; + private Validation v6; + + private Builder6(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + } + + public Builder7 combine(Validation v7) { + return new Builder7<>(v1, v2, v3, v4, v5, v6, v7); + } + + } + + final class Builder7 { + + private Validation v1; + private Validation v2; + private Validation v3; + private Validation v4; + private Validation v5; + private Validation v6; + private Validation v7; + + private Builder7(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + this.v7 = v7; + } + + public Builder8 combine(Validation v8) { + return new Builder8<>(v1, v2, v3, v4, v5, v6, v7, v8); + } + + } + + final class Builder8 { + + private Validation v1; + private Validation v2; + private Validation v3; + private Validation v4; + private Validation v5; + private Validation v6; + private Validation v7; + private Validation v8; + + private Builder8(Validation v1, Validation v2, Validation v3, Validation v4, Validation v5, Validation v6, Validation v7, Validation v8) { + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + this.v4 = v4; + this.v5 = v5; + this.v6 = v6; + this.v7 = v7; + this.v8 = v8; + } + + } +} diff --git a/src/main/java/com/utp/pry2/app/RepNumericas.java b/src/main/java/com/utp/pry2/app/RepNumericas.java index 56364c6..731a1c5 100644 --- a/src/main/java/com/utp/pry2/app/RepNumericas.java +++ b/src/main/java/com/utp/pry2/app/RepNumericas.java @@ -1,13 +1,9 @@ package com.utp.pry2.app; -import java.io.BufferedReader; -import java.io.InputStreamReader; import java.util.Optional; -import com.utp.Cli; -import com.utp.Traits.FromStr; - -import io.vavr.control.Validation; +import com.utp.io_vavrs.Validation; +import com.utp.utils.Cli; public class RepNumericas { @@ -19,23 +15,21 @@ public static void main(String[] args) { void spawn_cli() { // Enter data using BufferReader - var reader = new BufferedReader(new InputStreamReader(System.in)); while (true) { - // var input = Cli.read_non_empty_input("Ingrese un binario"); - var input = "0010101010101000101"; - var maybe_binario = BinaryString.from(input); + var input = Cli.read_non_empty_input("Ingrese un binario"); + var maybe_binario = BinaryString.from_str(input); if (maybe_binario.isInvalid()) { System.out.println(maybe_binario.getError()); continue; } - + input = maybe_binario.get().toString(); System.out.printf("Entrada: %s\n", input); System.out.println("Hexadecimal: 0x" + maybe_binario.get().to_hex_string()); var decimal = maybe_binario.get().to_int(); - System.out.printf("%s => Entero: ", input ); + decimal = maybe_binario.get().to_int(); + System.out.printf("%s => Entero: ", input); Utils.pretty_print_int(decimal); - System.out.println(""); - break; + System.out.println("\n"); } } } @@ -43,17 +37,17 @@ void spawn_cli() { class Utils { static void pretty_print_int(int num) { com.utp.pry1.app.Utils.pretty_print_int(num); - } } -class BinaryString implements FromStr { - public static Validation from(String input){ - return (new BinaryString(null)).from_str(input); - } - public Validation from_str(String input) { +class BinaryString { + public static Validation from_str(String input) { + // Strip leading zeroes because they don't affect the return value size + input = input.replaceFirst("^[0]*", ""); if (input.length() > BITS_SIZE) { - return Validation.invalid(String.format("`%s` is longer than the set character limit", input)); + return Validation.invalid( + String.format("`%s` is `%d` chars longer than the set character limit of `%d` chars", input, + input.length() - BITS_SIZE, BITS_SIZE)); } if (!input.matches("[01]+")) { return Validation.invalid(String.format("`%s` is not a valid binary string", input)); @@ -65,14 +59,20 @@ public Integer to_int() { if (cached_int.isPresent()) { return cached_int.get(); } - return Integer.parseInt(inner, 2); + cached_int = Optional.of(Integer.parseInt(inner, 2)); + return cached_int.get(); } public String to_hex_string() { return Integer.toHexString(to_int()); } - BinaryString(String inner) { + @Override + public String toString() { + return inner; + } + + private BinaryString(String inner) { this.inner = inner; } diff --git a/src/main/java/com/utp/Cli.java b/src/main/java/com/utp/utils/Cli.java similarity index 97% rename from src/main/java/com/utp/Cli.java rename to src/main/java/com/utp/utils/Cli.java index 8795bbe..f8575f9 100644 --- a/src/main/java/com/utp/Cli.java +++ b/src/main/java/com/utp/utils/Cli.java @@ -1,4 +1,4 @@ -package com.utp; +package com.utp.utils; import java.io.BufferedReader; import java.io.InputStreamReader;