code: /*
   * Copyright (c) 2019 the Eclipse Milo Authors
   *
   * This program and the accompanying materials are made
   * available under the terms of the Eclipse Public License 2.0
   * which is available at https://www.eclipse.org/legal/epl-2.0/
   *
   * SPDX-License-Identifier: EPL-2.0
   */
  
  package org.eclipse.milo.opcua.stack.core.channel.messages;
  
  import java.util.function.Consumer;
  
  import io.netty.buffer.ByteBuf;
  import io.netty.buffer.Unpooled;
  import org.eclipse.milo.opcua.stack.core.UaException;
  
  public class TcpMessageEncoder {
  
      public static ByteBuf encode(HelloMessage helloMessage) throws UaException {
          return encode(
              MessageType.Hello,
              (b) -> HelloMessage.encode(helloMessage, b),
              Unpooled.buffer()
          );
      }
  
      public static ByteBuf encode(AcknowledgeMessage acknowledgeMessage) throws UaException {
          return encode(
              MessageType.Acknowledge,
              b -> AcknowledgeMessage.encode(acknowledgeMessage, b),
              Unpooled.buffer()
          );
      }
  
      public static ByteBuf encode(ErrorMessage errorMessage) throws UaException {
          return encode(
              MessageType.Error,
              (b) -> ErrorMessage.encode(errorMessage, b),
              Unpooled.buffer()
          );
      }
  
      /**
       * Encode a simple UA TCP message.
       *
       * @param messageType    {@link MessageType#Hello}, {@link MessageType#Acknowledge}, or {@link MessageType#Error}.
       * @param messageEncoder a function that encodes the message payload.
       * @param buffer         the {@link ByteBuf} to encode into.
       */
      private static ByteBuf encode(
          MessageType messageType,
          Consumer<ByteBuf> messageEncoder,
          ByteBuf buffer) throws UaException {
  
          buffer.writeMediumLE(MessageType.toMediumInt(messageType));
          buffer.writeByte('F');
  
          int lengthIndex = buffer.writerIndex();
          buffer.writeIntLE(0);
  
          int indexBefore = buffer.writerIndex();
          messageEncoder.accept(buffer);
          int indexAfter = buffer.writerIndex();
          int bytesWritten = indexAfter - indexBefore;
  
          buffer.writerIndex(lengthIndex);
          buffer.writeIntLE(8 + bytesWritten);
          buffer.writerIndex(indexAfter);
  
          return buffer;
      }
  
  }
  