-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMulticodecDecoder.java
More file actions
130 lines (111 loc) · 4.25 KB
/
MulticodecDecoder.java
File metadata and controls
130 lines (111 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.apicatalog.multicodec;
import java.util.Objects;
import java.util.Optional;
import com.apicatalog.multicodec.Multicodec.Tag;
import com.apicatalog.multicodec.codec.MulticodecRegistry;
import com.apicatalog.uvarint.UVarInt;
/**
* A decoder for data encoded using the
* <a href="https://github.com/multiformats/multicodec">multicodec</a> format.
*
* <p>
* This class uses a {@link MulticodecRegistry} to look up codecs by their
* identifiers, and can decode encoded byte arrays back to their original data.
* </p>
*
* @see <a href=
* "https://github.com/multiformats/multicodec/blob/master/table.csv">
* Multicodec Codes Table</a>
*/
public class MulticodecDecoder {
protected final MulticodecRegistry registry;
/**
* Creates a new decoder backed by the given registry.
*
* @param registry the multicodec registry
*/
protected MulticodecDecoder(MulticodecRegistry registry) {
this.registry = registry;
}
/**
* Creates a new {@code MulticodecDecoder} instance initialized with all
* supported codecs.
*
* @return a new decoder instance containing all known codecs
*/
public static MulticodecDecoder getInstance() {
return new MulticodecDecoder(MulticodecRegistry.getInstance());
}
/**
* Creates a new {@code MulticodecDecoder} instance initialized with codecs
* matching the provided tags.
*
* <p>
* See the {@code codec} package for the complete list of included codecs.
* </p>
*
* @param tags one or more codec tags to match
* @return a new decoder instance containing only codecs with matching tags
*/
public static MulticodecDecoder getInstance(Tag... tags) {
Objects.requireNonNull(tags);
if (tags.length == 0) {
throw new IllegalArgumentException("At least one tag must be provided.");
}
return new MulticodecDecoder(MulticodecRegistry.getInstance(tags));
}
/**
* Creates a new {@code MulticodecDecoder} instance initialized with the given
* codecs.
*
* @param codecs one or more codecs to register
* @return a new decoder instance containing only the provided codecs
*/
public static MulticodecDecoder getInstance(Multicodec... codecs) {
Objects.requireNonNull(codecs);
if (codecs.length == 0) {
throw new IllegalArgumentException("At least one codec must be provided.");
}
return new MulticodecDecoder(MulticodecRegistry.getInstance(codecs));
}
/**
* Finds the codec in the registry corresponding to the given encoded value.
*
* @param encoded a byte array encoded as a multicodec value
* @return an {@link Optional} containing the matching codec, or an empty
* Optional if no match exists
* @throws NullPointerException if {@code encoded} is {@code null}
* @throws IllegalArgumentException if {@code encoded} is empty
*/
public Optional<Multicodec> getCodec(final byte[] encoded) {
Objects.requireNonNull(encoded);
if (encoded.length == 0) {
throw new IllegalArgumentException("The encoded value must be a non-empty byte array.");
}
final long code = UVarInt.decode(encoded);
return registry.getCodec(code);
}
/**
* Decodes the given encoded value by first determining its codec from the
* registry, then removing its multicodec prefix.
*
* @param encoded the encoded byte array to decode
* @return the decoded (original) byte array
* @throws NullPointerException if {@code encoded} is {@code null}
* @throws IllegalArgumentException if no codec can decode the value
*/
public byte[] decode(final byte[] encoded) throws IllegalArgumentException {
return getCodec(encoded)
.map(codec -> codec.decode(encoded))
.orElseThrow(() -> new IllegalArgumentException(
"Unsupported multicodec encoding [" + String.format("0x%hh, 0x%hh, ...", encoded[0], encoded[1]) + "]."));
}
/**
* Returns the underlying codec registry used by this decoder.
*
* @return the codec registry
*/
public MulticodecRegistry getRegistry() {
return registry;
}
}