001/* 002 * SPDX-License-Identifier: Apache-2.0 003 * 004 * Copyright 2024-2026 The Enola <https://enola.dev> Authors 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package dev.enola.common.convert; 019 020import com.google.common.primitives.UnsignedInteger; 021import com.google.common.primitives.UnsignedLong; 022 023import dev.enola.common.ByteSeq; 024 025import org.jspecify.annotations.Nullable; 026 027import java.io.IOException; 028import java.net.URISyntaxException; 029import java.nio.file.attribute.FileTime; 030import java.time.Instant; 031import java.time.LocalDate; 032import java.util.Optional; 033import java.util.UUID; 034 035public final class ObjectToStringBiConverters { 036 037 // TODO Add Locale aware Number converters (similar to TemporalAccessorToStringConverter) 038 039 public static final ObjectToStringBiConverter<String> STRING = 040 new ObjectToStringWithToStringBiConverter<>(String.class, input -> input); 041 042 public static final ObjectToStringBiConverter<Boolean> BOOLEAN = 043 new ObjectToStringWithToStringBiConverter<>(Boolean.class, Boolean::valueOf); 044 045 public static final ObjectToStringBiConverter<Byte> BYTE = 046 new ObjectToStringWithToStringBiConverter<>(Byte.class, Byte::valueOf); 047 048 public static final ObjectToStringBiConverter<Short> SHORT = 049 new ObjectToStringWithToStringBiConverter<>(Short.class, Short::valueOf); 050 051 // TODO UNSIGNED_BYTE 052 053 public static final ObjectToStringBiConverter<Short> UNSIGNED_SHORT = 054 new ObjectToStringBiConverter<>() { 055 @Override 056 public @Nullable String convertTo(@Nullable Short input) 057 throws ConversionException { 058 return Integer.toString(Short.toUnsignedInt(input)); 059 } 060 061 @Override 062 public @Nullable Short convertFrom(@Nullable String input) 063 throws ConversionException { 064 throw new IllegalStateException("TODO: Not implemented yet, add tests!"); 065 } 066 }; 067 068 public static final ObjectToStringBiConverter<Integer> INT = 069 new ObjectToStringWithToStringBiConverter<>(Integer.class, Integer::valueOf); 070 071 public static final ObjectToStringBiConverter<UnsignedInteger> UNSIGNED_INTEGER = 072 new ObjectToStringWithToStringBiConverter<>( 073 UnsignedInteger.class, UnsignedInteger::valueOf); 074 075 public static final ObjectToStringBiConverter<UnsignedLong> UNSIGNED_LONG = 076 new ObjectToStringWithToStringBiConverter<>(UnsignedLong.class, UnsignedLong::valueOf); 077 078 public static final ObjectToStringBiConverter<UUID> UUID = 079 new ObjectToStringWithToStringBiConverter<>(UUID.class, java.util.UUID::fromString); 080 081 public static final ObjectToStringBiConverter<java.net.URI> URI = 082 new ObjectToStringWithToStringBiConverter<>( 083 java.net.URI.class, 084 input -> { 085 try { 086 return new java.net.URI(input); 087 } catch (URISyntaxException e) { 088 throw new ConversionException(input, e); 089 } 090 }); 091 092 public static final ObjectToStringBiConverter<LocalDate> LOCAL_DATE = 093 new ObjectToStringWithToStringBiConverter<>(LocalDate.class, LocalDate::parse); 094 095 public static final ObjectToStringBiConverter<Instant> INSTANT = 096 // new ObjectToStringWithToStringBiConverter<>(Instant.class, Instant::parse); 097 TemporalAccessorToStringConverter.INSTANT; 098 099 public static final ObjectToStringBiConverter<FileTime> FILE_TIME = 100 new ObjectToStringWithToStringBiConverter<>( 101 // TODO According to FileTime#Instant(), it "can store points on the time-line 102 // further in the future and further in the past than Instant" - so no good?! 103 FileTime.class, input -> FileTime.from(Instant.parse(input))) { 104 @Override 105 @SuppressWarnings("unchecked") 106 public <X> Optional<X> convertToType(FileTime input, Class<X> type) 107 throws IOException { 108 if (Instant.class.equals(type)) 109 return (Optional<X>) Optional.of(input.toInstant()); 110 return super.convertToType(input, type); 111 } 112 }; 113 114 public static final ObjectToStringBiConverter<ByteSeq> MULTIBASE = new MultibaseConverter(); 115 116 private ObjectToStringBiConverters() {} 117}