View Javadoc
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 }