1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.apksig.util;
18 
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 
22 /**
23  * Abstract representation of a source of data.
24  *
25  * <p>This abstraction serves three purposes:
26  * <ul>
27  * <li>Transparent handling of different types of sources, such as {@code byte[]},
28  *     {@link java.nio.ByteBuffer}, {@link java.io.RandomAccessFile}, memory-mapped file.</li>
29  * <li>Support sources larger than 2 GB. If all sources were smaller than 2 GB, {@code ByteBuffer}
30  *     may have worked as the unifying abstraction.</li>
31  * <li>Support sources which do not fit into logical memory as a contiguous region.</li>
32  * </ul>
33  *
34  * <p>There are following ways to obtain a chunk of data from the data source:
35  * <ul>
36  * <li>Stream the chunk's data into a {@link DataSink} using
37  *     {@link #feed(long, long, DataSink) feed}. This is best suited for scenarios where there is no
38  *     need to have the chunk's data accessible at the same time, for example, when computing the
39  *     digest of the chunk. If you need to keep the chunk's data around after {@code feed}
40  *     completes, you must create a copy during {@code feed}. However, in that case the following
41  *     methods of obtaining the chunk's data may be more appropriate.</li>
42  * <li>Obtain a {@link ByteBuffer} containing the chunk's data using
43  *     {@link #getByteBuffer(long, int) getByteBuffer}. Depending on the data source, the chunk's
44  *     data may or may not be copied by this operation. This is best suited for scenarios where
45  *     you need to access the chunk's data in arbitrary order, but don't need to modify the data and
46  *     thus don't require a copy of the data.</li>
47  * <li>Copy the chunk's data to a {@link ByteBuffer} using
48  *     {@link #copyTo(long, int, ByteBuffer) copyTo}. This is best suited for scenarios where
49  *     you require a copy of the chunk's data, such as to when you need to modify the data.
50  *     </li>
51  * </ul>
52  */
53 public interface DataSource {
54 
55     /**
56      * Returns the amount of data (in bytes) contained in this data source.
57      */
size()58     long size();
59 
60     /**
61      * Feeds the specified chunk from this data source into the provided sink.
62      *
63      * @param offset index (in bytes) at which the chunk starts inside data source
64      * @param size size (in bytes) of the chunk
65      *
66      * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if
67      *         {@code offset + size} is greater than {@link #size()}.
68      */
feed(long offset, long size, DataSink sink)69     void feed(long offset, long size, DataSink sink) throws IOException;
70 
71     /**
72      * Returns a buffer holding the contents of the specified chunk of data from this data source.
73      * Changes to the data source are not guaranteed to be reflected in the returned buffer.
74      * Similarly, changes in the buffer are not guaranteed to be reflected in the data source.
75      *
76      * <p>The returned buffer's position is {@code 0}, and the buffer's limit and capacity is
77      * {@code size}.
78      *
79      * @param offset index (in bytes) at which the chunk starts inside data source
80      * @param size size (in bytes) of the chunk
81      *
82      * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if
83      *         {@code offset + size} is greater than {@link #size()}.
84      */
getByteBuffer(long offset, int size)85     ByteBuffer getByteBuffer(long offset, int size) throws IOException;
86 
87     /**
88      * Copies the specified chunk from this data source into the provided destination buffer,
89      * advancing the destination buffer's position by {@code size}.
90      *
91      * @param offset index (in bytes) at which the chunk starts inside data source
92      * @param size size (in bytes) of the chunk
93      *
94      * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if
95      *         {@code offset + size} is greater than {@link #size()}.
96      */
copyTo(long offset, int size, ByteBuffer dest)97     void copyTo(long offset, int size, ByteBuffer dest) throws IOException;
98 
99     /**
100      * Returns a data source representing the specified region of data of this data source. Changes
101      * to data represented by this data source will also be visible in the returned data source.
102      *
103      * @param offset index (in bytes) at which the region starts inside data source
104      * @param size size (in bytes) of the region
105      *
106      * @throws IndexOutOfBoundsException if {@code offset} or {@code size} is negative, or if
107      *         {@code offset + size} is greater than {@link #size()}.
108      */
slice(long offset, long size)109     DataSource slice(long offset, long size);
110 }
111