1 /* 2 * hunt-time: A time library for D programming language. 3 * 4 * Copyright (C) 2015-2018 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.time.Ser; 13 14 import hunt.stream.Externalizable; 15 import hunt.Exceptions; 16 // import hunt.io.InvalidClassException; 17 import hunt.stream.ObjectInput; 18 import hunt.stream.ObjectOutput; 19 // import hunt.io.StreamCorruptedException; 20 // import hunt.time.Duration; 21 // import hunt.time.Instant; 22 // import hunt.time.LocalDate; 23 // import hunt.time.LocalDateTime; 24 // import hunt.time.LocalTime; 25 // import hunt.time.ZoneRegion; 26 // import hunt.time.ZoneOffset; 27 // import hunt.time.ZonedDateTime; 28 // import hunt.time.OffsetTime; 29 // import hunt.time.OffsetDateTime; 30 // import hunt.time.Year; 31 // import hunt.time.YearMonth; 32 // import hunt.time.MonthDay; 33 // import hunt.time.Period; 34 35 /** 36 * The shared serialization delegate for this package. 37 * 38 * @implNote 39 * This class wraps the object being serialized, and takes a byte representing the type of the class to 40 * be serialized. This byte can also be used for versioning the serialization format. In this case another 41 * byte flag would be used _in order to specify an alternative version of the type format. 42 * For example {@code LOCAL_DATE_TYPE_VERSION_2 = 21}. 43 * !(p) 44 * In order to serialize the object it writes its byte and then calls back to the appropriate class where 45 * the serialization is performed. In order to deserialize the object it read _in the type byte, switching 46 * _in order to select which class to call back into. 47 * !(p) 48 * The serialization format is determined on a per class basis. In the case of field based classes each 49 * of the fields is written _out with an appropriate size format _in descending order of the field's size. For 50 * example _in the case of {@link LocalDate} year is written before month. Composite classes, such as 51 * {@link LocalDateTime} are serialized as one object. 52 * !(p) 53 * This class is mutable and should be created once per serialization. 54 * 55 * @serial include 56 * @since 1.8 57 */ 58 final class Ser : Externalizable { 59 60 /** 61 * Serialization version. 62 */ 63 private enum long serialVersionUID = -7683839454370182990L; 64 65 enum byte DURATION_TYPE = 1; 66 enum byte INSTANT_TYPE = 2; 67 enum byte LOCAL_DATE_TYPE = 3; 68 enum byte LOCAL_TIME_TYPE = 4; 69 enum byte LOCAL_DATE_TIME_TYPE = 5; 70 enum byte ZONE_DATE_TIME_TYPE = 6; 71 enum byte ZONE_REGION_TYPE = 7; 72 enum byte ZONE_OFFSET_TYPE = 8; 73 enum byte OFFSET_TIME_TYPE = 9; 74 enum byte OFFSET_DATE_TIME_TYPE = 10; 75 enum byte YEAR_TYPE = 11; 76 enum byte YEAR_MONTH_TYPE = 12; 77 enum byte MONTH_DAY_TYPE = 13; 78 enum byte PERIOD_TYPE = 14; 79 80 /** The type being serialized. */ 81 private byte type; 82 /** The object being serialized. */ 83 private Object object; 84 85 /** 86 * Constructor for deserialization. 87 */ 88 public this() { 89 } 90 91 /** 92 * Creates an instance for serialization. 93 * 94 * @param type the type 95 * @param object the object 96 */ 97 this(byte type, Object object) { 98 this.type = type; 99 this.object = object; 100 } 101 102 //----------------------------------------------------------------------- 103 /** 104 * Implements the {@code Externalizable} interface to write the object. 105 * @serialData 106 * 107 * Each serializable class is mapped to a type that is the first byte 108 * _in the stream. Refer to each class {@code writeReplace} 109 * serialized form for the value of the type and sequence of values for the type. 110 * !(ul) 111 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Duration">Duration.writeReplace</a> 112 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Instant">Instant.writeReplace</a> 113 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalDate">LocalDate.writeReplace</a> 114 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalDateTime">LocalDateTime.writeReplace</a> 115 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalTime">LocalTime.writeReplace</a> 116 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.MonthDay">MonthDay.writeReplace</a> 117 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.OffsetTime">OffsetTime.writeReplace</a> 118 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.OffsetDateTime">OffsetDateTime.writeReplace</a> 119 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Period">Period.writeReplace</a> 120 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Year">Year.writeReplace</a> 121 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.YearMonth">YearMonth.writeReplace</a> 122 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZoneId">ZoneId.writeReplace</a> 123 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZoneOffset">ZoneOffset.writeReplace</a> 124 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZonedDateTime">ZonedDateTime.writeReplace</a> 125 * </ul> 126 * 127 * @param _out the data stream to write to, not null 128 */ 129 override 130 public void writeExternal(ObjectOutput _out) /*throws IOException*/ { 131 writeInternal(type, object, _out); 132 } 133 134 static void writeInternal(byte type, Object object, ObjectOutput _out) /*throws IOException*/ { 135 // _out.writeByte(type); 136 // switch (type) { 137 // case DURATION_TYPE: 138 // (cast(Duration) object).writeExternal(_out); 139 // break; 140 // case INSTANT_TYPE: 141 // (cast(Instant) object).writeExternal(_out); 142 // break; 143 // case LOCAL_DATE_TYPE: 144 // (cast(LocalDate) object).writeExternal(_out); 145 // break; 146 // case LOCAL_DATE_TIME_TYPE: 147 // (cast(LocalDateTime) object).writeExternal(_out); 148 // break; 149 // case LOCAL_TIME_TYPE: 150 // (cast(LocalTime) object).writeExternal(_out); 151 // break; 152 // case ZONE_REGION_TYPE: 153 // (cast(ZoneRegion) object).writeExternal(_out); 154 // break; 155 // case ZONE_OFFSET_TYPE: 156 // (cast(ZoneOffset) object).writeExternal(_out); 157 // break; 158 // case ZONE_DATE_TIME_TYPE: 159 // (cast(ZonedDateTime) object).writeExternal(_out); 160 // break; 161 // case OFFSET_TIME_TYPE: 162 // (cast(OffsetTime) object).writeExternal(_out); 163 // break; 164 // case OFFSET_DATE_TIME_TYPE: 165 // (cast(OffsetDateTime) object).writeExternal(_out); 166 // break; 167 // case YEAR_TYPE: 168 // (cast(Year) object).writeExternal(_out); 169 // break; 170 // case YEAR_MONTH_TYPE: 171 // (cast(YearMonth) object).writeExternal(_out); 172 // break; 173 // case MONTH_DAY_TYPE: 174 // (cast(MonthDay) object).writeExternal(_out); 175 // break; 176 // case PERIOD_TYPE: 177 // (cast(Period) object).writeExternal(_out); 178 // break; 179 // default: 180 // throw new InvalidClassException("Unknown serialized type"); 181 // } 182 } 183 184 //----------------------------------------------------------------------- 185 /** 186 * Implements the {@code Externalizable} interface to read the object. 187 * @serialData 188 * 189 * The streamed type and parameters defined by the type's {@code writeReplace} 190 * method are read and passed to the corresponding static factory for the type 191 * to create a new instance. That instance is returned as the de-serialized 192 * {@code Ser} object. 193 * 194 * !(ul) 195 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Duration">Duration</a> - {@code Duration.ofSeconds(seconds, nanos);} 196 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Instant">Instant</a> - {@code Instant.ofEpochSecond(seconds, nanos);} 197 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalDate">LocalDate</a> - {@code LocalDate.of(year, month, day);} 198 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalDateTime">LocalDateTime</a> - {@code LocalDateTime.of(date, time);} 199 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.LocalTime">LocalTime</a> - {@code LocalTime.of(hour, minute, second, nano);} 200 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.MonthDay">MonthDay</a> - {@code MonthDay.of(month, day);} 201 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.OffsetTime">OffsetTime</a> - {@code OffsetTime.of(time, offset);} 202 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.OffsetDateTime">OffsetDateTime</a> - {@code OffsetDateTime.of(dateTime, offset);} 203 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Period">Period</a> - {@code Period.of(years, months, days);} 204 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.Year">Year</a> - {@code Year.of(year);} 205 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.YearMonth">YearMonth</a> - {@code YearMonth.of(year, month);} 206 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZonedDateTime">ZonedDateTime</a> - {@code ZonedDateTime.ofLenient(dateTime, offset, zone);} 207 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZoneId">ZoneId</a> - {@code ZoneId.of(id);} 208 * !(li)<a href="{@docRoot}/serialized-form.html#hunt.time.ZoneOffset">ZoneOffset</a> - {@code (offsetByte == 127 ? ZoneOffset.ofTotalSeconds(_in.readInt()) : ZoneOffset.ofTotalSeconds(offsetByte * 900));} 209 * </ul> 210 * 211 * @param _in the data to read, not null 212 */ 213 public void readExternal(ObjectInput _in) /*throws IOException, ClassNotFoundException*/ { 214 type = _in.readByte(); 215 object = readInternal(type, _in); 216 } 217 218 static Object read(ObjectInput _in) /*throws IOException, ClassNotFoundException*/{ 219 byte type = _in.readByte(); 220 return readInternal(type, _in); 221 } 222 223 private static Object readInternal(byte type, ObjectInput _in) /*throws IOException, ClassNotFoundException*/ { 224 // switch (type) { 225 // case DURATION_TYPE: return Duration.readExternal(_in); 226 // case INSTANT_TYPE: return Instant.readExternal(_in); 227 // case LOCAL_DATE_TYPE: return LocalDate.readExternal(_in); 228 // case LOCAL_DATE_TIME_TYPE: return LocalDateTime.readExternal(_in); 229 // case LOCAL_TIME_TYPE: return LocalTime.readExternal(_in); 230 // case ZONE_DATE_TIME_TYPE: return ZonedDateTime.readExternal(_in); 231 // case ZONE_OFFSET_TYPE: return ZoneOffset.readExternal(_in); 232 // case ZONE_REGION_TYPE: return ZoneRegion.readExternal(_in); 233 // case OFFSET_TIME_TYPE: return OffsetTime.readExternal(_in); 234 // case OFFSET_DATE_TIME_TYPE: return OffsetDateTime.readExternal(_in); 235 // case YEAR_TYPE: return Year.readExternal(_in); 236 // case YEAR_MONTH_TYPE: return YearMonth.readExternal(_in); 237 // case MONTH_DAY_TYPE: return MonthDay.readExternal(_in); 238 // case PERIOD_TYPE: return Period.readExternal(_in); 239 // default: 240 // throw new Exception("Unknown serialized type"); 241 // } 242 return null; 243 } 244 245 /** 246 * Returns the object that will replace this one. 247 * 248 * @return the read object, should never be null 249 */ 250 private Object readResolve() { 251 return object; 252 } 253 254 }