1 /*
2 * Copyright (C) 2009, The Android Open Source Project
3 * Copyright (C) 2009, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2018, David Pursehouse <david.pursehouse@gmail.com> and others
5 *
6 * This program and the accompanying materials are made available under the
7 * terms of the Eclipse Distribution License v. 1.0 which is available at
8 * https://www.eclipse.org/org/documents/edl-v10.php.
9 *
10 * SPDX-License-Identifier: BSD-3-Clause
11 */
12
13 package org.eclipse.jgit.lib;
14
15 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
16
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.OutputStream;
20
21 import org.eclipse.jgit.annotations.NonNull;
22 import org.eclipse.jgit.annotations.Nullable;
23 import org.eclipse.jgit.util.IO;
24
25 /**
26 * Helper to serialize {@link ObjectId} instances. {@link ObjectId} is already
27 * serializable, but this class provides methods to handle null and non-null
28 * instances.
29 *
30 * @since 4.11
31 */
32 public class ObjectIdSerializer {
33 /*
34 * Marker to indicate a null ObjectId instance.
35 */
36 private static final byte NULL_MARKER = 0;
37
38 /*
39 * Marker to indicate a non-null ObjectId instance.
40 */
41 private static final byte NON_NULL_MARKER = 1;
42
43 /**
44 * Write a possibly null {@link ObjectId} to the stream, using markers to
45 * differentiate null and non-null instances.
46 *
47 * <p>
48 * If the id is non-null, writes a {@link #NON_NULL_MARKER} followed by the
49 * id's words. If it is null, writes a {@link #NULL_MARKER} and nothing
50 * else.
51 *
52 * @param out
53 * the output stream
54 * @param id
55 * the object id to serialize; may be null
56 * @throws IOException
57 * the stream writing failed
58 */
59 public static void write(OutputStream out, @Nullable AnyObjectId id)
60 throws IOException {
61 if (id != null) {
62 out.write(NON_NULL_MARKER);
63 writeWithoutMarker(out, id);
64 } else {
65 out.write(NULL_MARKER);
66 }
67 }
68
69 /**
70 * Write a non-null {@link ObjectId} to the stream.
71 *
72 * @param out
73 * the output stream
74 * @param id
75 * the object id to serialize; never null
76 * @throws IOException
77 * the stream writing failed
78 * @since 4.11
79 */
80 public static void writeWithoutMarker(OutputStream out, @NonNull AnyObjectId id)
81 throws IOException {
82 id.copyRawTo(out);
83 }
84
85 /**
86 * Read a possibly null {@link ObjectId} from the stream.
87 *
88 * Reads the first byte of the stream, which is expected to be either
89 * {@link #NON_NULL_MARKER} or {@link #NULL_MARKER}.
90 *
91 * @param in
92 * the input stream
93 * @return the object id, or null
94 * @throws IOException
95 * there was an error reading the stream
96 */
97 @Nullable
98 public static ObjectId read(InputStream in) throws IOException {
99 byte marker = (byte) in.read();
100 switch (marker) {
101 case NULL_MARKER:
102 return null;
103 case NON_NULL_MARKER:
104 return readWithoutMarker(in);
105 default:
106 throw new IOException("Invalid flag before ObjectId: " + marker); //$NON-NLS-1$
107 }
108 }
109
110 /**
111 * Read a non-null {@link ObjectId} from the stream.
112 *
113 * @param in
114 * the input stream
115 * @return the object id; never null
116 * @throws IOException
117 * there was an error reading the stream
118 * @since 4.11
119 */
120 @NonNull
121 public static ObjectId readWithoutMarker(InputStream in) throws IOException {
122 final byte[] b = new byte[OBJECT_ID_LENGTH];
123 IO.readFully(in, b, 0, OBJECT_ID_LENGTH);
124 return ObjectId.fromRaw(b);
125 }
126
127 private ObjectIdSerializer() {
128 }
129 }