All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sonarsource.analyzer.commons.LengthPrefixSerializer Maven / Gradle / Ivy

There is a newer version: 2.16.0.3141
Show newest version
/*
 * SonarSource Analyzers Commons
 * Copyright (C) 2009-2024 SonarSource SA
 * mailto:info AT sonarsource DOT com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.sonarsource.analyzer.commons;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A utility class to de/serialize a List and Map from/to byte[].
 * Simple length-prefixed serialization is used without any integrity checks.
 * Lengths are saved as int. Thus, the maximum size of an entry is Integer.MAX_VALUE.
 */
public class LengthPrefixSerializer {

  private LengthPrefixSerializer() {
    // utility
  }

  public static byte[] serializeList(List toSerializeList) throws IOException {
    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         DataOutputStream dos = new DataOutputStream(byteArrayOutputStream)) {
      for (byte[] toSerializeElement : toSerializeList) {
        writeLengthAndBytes(dos, toSerializeElement);
      }
      return byteArrayOutputStream.toByteArray();
    }
  }

  public static List unserializeList(byte[] data) throws IOException {
    return unserializeList(new ByteArrayInputStream(data));
  }

  public static List unserializeList(InputStream data) throws IOException {
    List result = new ArrayList<>();
    try (DataInputStream dis = new DataInputStream(data)) {
      while (dis.available() > 0) {
        result.add(readBytes(dis));
      }
    }
    return result;
  }

  public static byte[] serializeMap(Map toSerializeMap) throws IOException {
    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         DataOutputStream dos = new DataOutputStream(byteArrayOutputStream)) {
      for (Map.Entry toSerializeElement : toSerializeMap.entrySet()) {
        writeLengthAndBytes(dos, toSerializeElement.getKey().getBytes(StandardCharsets.UTF_8));
        writeLengthAndBytes(dos, toSerializeElement.getValue());
      }
      return byteArrayOutputStream.toByteArray();
    }
  }

  public static Map unserializeMap(byte[] data) throws IOException {
    return unserializeMap(new ByteArrayInputStream(data));
  }

  public static Map unserializeMap(InputStream data) throws IOException {
    Map result = new HashMap<>();
    try (DataInputStream dis = new DataInputStream(data)) {
      while (dis.available() > 0) {
        String key = new String(readBytes(dis), StandardCharsets.UTF_8);
        byte[] value = readBytes(dis);
        result.put(key, value);
      }
    }
    return result;
  }

  private static byte[] readBytes(DataInputStream dis) throws IOException {
    int length = dis.readInt();
    validateLength(length);
    byte[] bytes = new byte[length];
    dis.readFully(bytes);
    return bytes;
  }

  private static void writeLengthAndBytes(DataOutputStream dos, byte[] bytes) throws IOException {
    dos.writeInt(bytes.length);
    dos.write(bytes);
  }

  private static void validateLength(int length) throws IOException {
    if (length < 0) {
      throw new IOException("Invalid length while unserializing: " + length);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy