001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2025 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
006 * the License. You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
011 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
012 * specific language governing permissions and limitations under the License.
013 */
014package org.microbean.attributes;
015
016import java.lang.constant.ClassDesc;
017import java.lang.constant.DynamicConstantDesc;
018import java.lang.constant.MethodHandleDesc;
019import java.lang.constant.MethodTypeDesc;
020
021import java.util.Optional;
022
023import static java.lang.constant.ConstantDescs.BSM_INVOKE;
024import static java.lang.constant.ConstantDescs.CD_String;
025import static java.lang.constant.ConstantDescs.CD_char;
026import static java.lang.constant.ConstantDescs.CD_int;
027import static java.lang.constant.DirectMethodHandleDesc.Kind.STATIC;
028import static java.lang.constant.DirectMethodHandleDesc.Kind.VIRTUAL;
029
030/**
031 * A {@link Value} whose value is a {@code char}.
032 *
033 * @param value the value
034 *
035 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
036 */
037public final record CharValue(char value) implements Value<CharValue> {
038
039  @Override // Comparable<CharValue>
040  public final int compareTo(final CharValue other) {
041    if (other == null) {
042      return -1;
043    } else if (this.equals(other)) {
044      return 0;
045    }
046    return this.value() > other.value() ? 1 : -1;
047  }
048
049  @Override // Constable
050  public final Optional<DynamicConstantDesc<CharValue>> describeConstable() {
051    final ClassDesc cd = ClassDesc.of(this.getClass().getName());
052    return
053      Optional.of(DynamicConstantDesc.of(BSM_INVOKE,
054                                         MethodHandleDesc.ofMethod(STATIC,
055                                                                   cd,
056                                                                   "of",
057                                                                   MethodTypeDesc.of(cd,
058                                                                                     CD_char)),
059                                         DynamicConstantDesc.of(BSM_INVOKE,
060                                                                MethodHandleDesc.ofMethod(VIRTUAL,
061                                                                                          CD_String,
062                                                                                          "charAt",
063                                                                                          MethodTypeDesc.of(CD_char,
064                                                                                                            CD_int)),
065                                                                String.valueOf(this.value()),
066                                                                Integer.valueOf(0))));
067  }
068
069  @Override // Record
070  public final boolean equals(final Object other) {
071    return
072      other == this ||
073      // Follow java.lang.annotation.Annotation requirements.
074      other != null && other.getClass() == this.getClass() && this.value() == ((CharValue)other).value();
075  }
076
077  @Override // Record
078  public final int hashCode() {
079    // Follow java.lang.annotation.Annotation requirements.
080    return Character.valueOf(this.value()).hashCode();
081  }
082
083  @Override // Record
084  public final String toString() {
085    return String.valueOf(this.value());
086  }
087
088  /**
089   * Returns a {@link CharValue} suitable for the supplied arguments.
090   *
091   * @param c a {@code char}
092   *
093   * @return a non-{@code null} {@link CharValue}
094   */
095  public static final CharValue of(final char c) {
096    return new CharValue(c);
097  }
098
099}