1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package hat.ifacemapper;
 27 
 28 import hat.ifacemapper.accessor.Accessors;
 29 //import jdk.internal.vm.annotation.Stable;
 30 
 31 import java.lang.foreign.GroupLayout;
 32 import java.lang.invoke.MethodHandle;
 33 import java.lang.invoke.MethodHandles;
 34 import java.util.function.BiFunction;
 35 import java.util.function.UnaryOperator;
 36 
 37 abstract class AbstractSegmentMapper<T> implements SegmentMapper<T> {
 38 
 39    // @Stable
 40     private final MethodHandles.Lookup lookup;
 41   //  @Stable
 42     private final Class<T> type;
 43   //  @Stable
 44     private final GroupLayout layout;
 45     private final BoundSchema<?> boundSchema;
 46     private final boolean leaf;
 47     private final MapperCache mapperCache;
 48     protected Accessors accessors;
 49 
 50     protected AbstractSegmentMapper(MethodHandles.Lookup lookup,
 51                                     Class<T> type,
 52 
 53                                     GroupLayout layout,
 54                                     BoundSchema<?> boundSchema,
 55                                     boolean leaf,
 56 
 57                                     UnaryOperator<Class<T>> typeInvariantChecker,
 58                                     BiFunction<Class<?>, GroupLayout, Accessors> accessorFactory) {
 59         this.lookup = lookup;
 60         this.type = typeInvariantChecker.apply(type);
 61         this.boundSchema = boundSchema;
 62         this.layout = layout;
 63         this.leaf = leaf;
 64         this.mapperCache = MapperCache.of(lookup);
 65         this.accessors = accessorFactory.apply(type, layout);
 66 
 67      /*   List<Method> unsupportedAccessors = accessors.stream(k -> !k.isSupportedFor(valueType))
 68                 .map(AccessorInfo::method)
 69                 .toList();
 70         if (!unsupportedAccessors.isEmpty()) {
 71             throw new IllegalArgumentException(
 72                     "The following accessors are not supported for " + valueType + ": " + unsupportedAccessors);
 73         } */
 74         MapperUtil.assertMappingsCorrectAndTotal(type, layout, accessors);
 75     }
 76 
 77     @Override
 78     public final Class<T> type() {
 79         return type;
 80     }
 81 
 82     @Override
 83     public final GroupLayout layout() {
 84         return layout;
 85     }
 86     @Override
 87     public final BoundSchema<?> boundSchema() {
 88         return boundSchema;
 89     }
 90 
 91     @Override
 92     public final String toString() {
 93         return getClass().getSimpleName() + "[" +
 94                 "lookup=" + lookup + ", " +
 95                 "type=" + type + ", " +
 96                 "layout=" + layout +
 97                 "hatData=" + ((boundSchema==null)?"null":boundSchema) + ", " +
 98                 "]";
 99     }
100 
101     // Protected methods
102 
103     protected final MethodHandles.Lookup lookup() {
104         return lookup;
105     }
106 
107     protected final Accessors accessors() {
108         return accessors;
109     }
110 
111     protected final MapperCache mapperCache() {
112         return mapperCache;
113     }
114 
115     protected final boolean isLeaf() {
116         return leaf;
117     }
118 
119     // Abstract methods
120 
121     // -> (MemorySegment, long)T if isLeaf()
122     // -> (MemorySegment, long)Object if !isLeaf()
123     protected abstract MethodHandle computeGetHandle();
124 
125     // (MemorySegment, long, T)void if isLeaf()
126     // (MemorySegment, long, Object)void if !isLeaf()
127     protected abstract MethodHandle computeSetHandle();
128 
129 }