// Copyright 2008 Google Inc. All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.gerrit.server.ioutil;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.gerrit.reviewdb.client.CodedEnum;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.eclipse.jgit.util.IO;

public class BasicSerialization {
  private static final byte[] NO_BYTES = {};

  private static int safeRead(InputStream input) throws IOException {
    final int b = input.read();
    if (b == -1) {
      throw new EOFException();
    }
    return b;
  }

  /** Read a fixed-width 64 bit integer in network byte order (big-endian). */
  public static long readFixInt64(InputStream input) throws IOException {
    final long h = readFixInt32(input);
    final long l = readFixInt32(input) & 0xFFFFFFFFL;
    return (h << 32) | l;
  }

  /** Write a fixed-width 64 bit integer in network byte order (big-endian). */
  public static void writeFixInt64(OutputStream output, long val) throws IOException {
    writeFixInt32(output, (int) (val >>> 32));
    writeFixInt32(output, (int) (val & 0xFFFFFFFFL));
  }

  /** Read a fixed-width 32 bit integer in network byte order (big-endian). */
  public static int readFixInt32(InputStream input) throws IOException {
    final int b1 = safeRead(input);
    final int b2 = safeRead(input);
    final int b3 = safeRead(input);
    final int b4 = safeRead(input);
    return (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
  }

  /** Write a fixed-width 32 bit integer in network byte order (big-endian). */
  public static void writeFixInt32(OutputStream output, int val) throws IOException {
    output.write((val >>> 24) & 0xFF);
    output.write((val >>> 16) & 0xFF);
    output.write((val >>> 8) & 0xFF);
    output.write(val & 0xFF);
  }

  /** Read a varint from the input, one byte at a time. */
  public static int readVarInt32(InputStream input) throws IOException {
    int result = 0;
    int offset = 0;
    for (; offset < 32; offset += 7) {
      final int b = safeRead(input);
      result |= (b & 0x7f) << offset;
      if ((b & 0x80) == 0) {
        return result;
      }
    }
    throw new EOFException();
  }

  /** Write a varint; value is treated as an unsigned value. */
  public static void writeVarInt32(OutputStream output, int value) throws IOException {
    while (true) {
      if ((value & ~0x7F) == 0) {
        output.write(value);
        return;
      }
      output.write((value & 0x7F) | 0x80);
      value >>>= 7;
    }
  }

  /** Read a fixed length byte array whose length is specified as a varint. */
  public static byte[] readBytes(InputStream input) throws IOException {
    final int len = readVarInt32(input);
    if (len == 0) {
      return NO_BYTES;
    }
    final byte[] buf = new byte[len];
    IO.readFully(input, buf, 0, len);
    return buf;
  }

  /** Write a byte array prefixed by its length in a varint. */
  public static void writeBytes(OutputStream output, byte[] data) throws IOException {
    writeBytes(output, data, 0, data.length);
  }

  /** Write a byte array prefixed by its length in a varint. */
  public static void writeBytes(final OutputStream output, byte[] data, int offset, int len)
      throws IOException {
    writeVarInt32(output, len);
    output.write(data, offset, len);
  }

  /** Read a UTF-8 string, prefixed by its byte length in a varint. */
  public static String readString(InputStream input) throws IOException {
    final byte[] bin = readBytes(input);
    if (bin.length == 0) {
      return null;
    }
    return new String(bin, 0, bin.length, UTF_8);
  }

  /** Write a UTF-8 string, prefixed by its byte length in a varint. */
  public static void writeString(OutputStream output, String s) throws IOException {
    if (s == null) {
      writeVarInt32(output, 0);
    } else {
      writeBytes(output, s.getBytes(UTF_8));
    }
  }

  /** Read an enum whose code is stored as a varint. */
  public static <T extends CodedEnum> T readEnum(InputStream input, T[] all) throws IOException {
    final int val = readVarInt32(input);
    for (T t : all) {
      if (t.getCode() == val) {
        return t;
      }
    }
    throw new IOException("Invalid enum " + val + " for " + all[0].getClass());
  }

  /** Write an enum whose code is stored as a varint. */
  public static <T extends CodedEnum> void writeEnum(OutputStream output, T e) throws IOException {
    writeVarInt32(output, e.getCode());
  }

  private BasicSerialization() {}
}
