Add method to register listener for unknown msg
[openflowjava.git] / openflow-protocol-impl / src / main / java / org / opendaylight / openflowjava / protocol / impl / deserialization / factories / OF10StatsReplyMessageFactory.java
1 /*
2  * Copyright (c) 2013 Pantheon Technologies s.r.o. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.openflowjava.protocol.impl.deserialization.factories;
10
11 import io.netty.buffer.ByteBuf;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
16 import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistryInjector;
17 import org.opendaylight.openflowjava.protocol.api.extensibility.OFDeserializer;
18 import org.opendaylight.openflowjava.protocol.api.keys.MessageCodeKey;
19 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
20 import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMaker;
21 import org.opendaylight.openflowjava.protocol.impl.util.CodeKeyMakerFactory;
22 import org.opendaylight.openflowjava.protocol.impl.util.ListDeserializer;
23 import org.opendaylight.openflowjava.protocol.impl.util.OF10MatchDeserializer;
24 import org.opendaylight.openflowjava.util.ByteBufUtils;
25 import org.opendaylight.openflowjava.util.ExperimenterDeserializerKeyFactory;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.actions.grouping.Action;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartRequestFlags;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.experimenter.core.ExperimenterDataOfChoice;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyAggregateCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCase;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyDescCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCase;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyExperimenterCaseBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyFlowCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCase;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyPortStatsCaseBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyQueueCaseBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCase;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.MultipartReplyTableCaseBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.aggregate._case.MultipartReplyAggregateBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.desc._case.MultipartReplyDescBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.experimenter._case.MultipartReplyExperimenterBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.MultipartReplyFlowBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStats;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.flow._case.multipart.reply.flow.FlowStatsBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.MultipartReplyPortStatsBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStats;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.port.stats._case.multipart.reply.port.stats.PortStatsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.MultipartReplyQueueBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStats;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.queue._case.multipart.reply.queue.QueueStatsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.MultipartReplyTableBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStats;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.multipart.reply.multipart.reply.body.multipart.reply.table._case.multipart.reply.table.TableStatsBuilder;
63
64 /**
65  * Translates StatsReply messages (OpenFlow v1.0)
66  *
67  * @author michal.polkorab
68  */
69 public class OF10StatsReplyMessageFactory implements OFDeserializer<MultipartReplyMessage>,
70         DeserializerRegistryInjector {
71
72     private static final int DESC_STR_LEN = 256;
73     private static final int SERIAL_NUM_LEN = 32;
74     private static final byte PADDING_IN_FLOW_STATS_HEADER = 1;
75     private static final byte PADDING_IN_FLOW_STATS_HEADER_02 = 6;
76     private static final byte PADDING_IN_AGGREGATE_HEADER = 4;
77     private static final byte PADDING_IN_TABLE_HEADER = 3;
78     private static final byte MAX_TABLE_NAME_LENGTH = 32;
79     private static final byte PADDING_IN_PORT_STATS_HEADER = 6;
80     private static final byte PADDING_IN_QUEUE_HEADER = 2;
81     private static final byte LENGTH_OF_FLOW_STATS = 88;
82     private static final int TABLE_STATS_LENGTH = 64;
83     private DeserializerRegistry registry;
84
85     @Override
86     public MultipartReplyMessage deserialize(ByteBuf rawMessage) {
87         MultipartReplyMessageBuilder builder = new MultipartReplyMessageBuilder();
88         builder.setVersion((short) EncodeConstants.OF10_VERSION_ID);
89         builder.setXid(rawMessage.readUnsignedInt());
90         int type = rawMessage.readUnsignedShort();
91         builder.setType(MultipartType.forValue(type));
92         builder.setFlags(new MultipartRequestFlags((rawMessage.readUnsignedShort() & 0x01) != 0));
93         switch (MultipartType.forValue(type)) {
94             case OFPMPDESC:
95                 builder.setMultipartReplyBody(setDesc(rawMessage));
96                 break;
97             case OFPMPFLOW:
98                 builder.setMultipartReplyBody(setFlow(rawMessage));
99                 break;
100             case OFPMPAGGREGATE:
101                 builder.setMultipartReplyBody(setAggregate(rawMessage));
102                 break;
103             case OFPMPTABLE:
104                 builder.setMultipartReplyBody(setTable(rawMessage));
105                 break;
106             case OFPMPPORTSTATS:
107                 builder.setMultipartReplyBody(setPortStats(rawMessage));
108                 break;
109             case OFPMPQUEUE:
110                 builder.setMultipartReplyBody(setQueue(rawMessage));
111                 break;
112             case OFPMPEXPERIMENTER:
113                 builder.setMultipartReplyBody(setExperimenter(rawMessage));
114                 break;
115             default:
116                 break;
117         }
118         return builder.build();
119     }
120
121     private static MultipartReplyDescCase setDesc(ByteBuf input) {
122         MultipartReplyDescCaseBuilder caseBuilder = new MultipartReplyDescCaseBuilder();
123         MultipartReplyDescBuilder descBuilder = new MultipartReplyDescBuilder();
124         byte[] mfrDescBytes = new byte[DESC_STR_LEN];
125         input.readBytes(mfrDescBytes);
126         String mfrDesc = new String(mfrDescBytes);
127         descBuilder.setMfrDesc(mfrDesc.trim());
128         byte[] hwDescBytes = new byte[DESC_STR_LEN];
129         input.readBytes(hwDescBytes);
130         String hwDesc = new String(hwDescBytes);
131         descBuilder.setHwDesc(hwDesc.trim());
132         byte[] swDescBytes = new byte[DESC_STR_LEN];
133         input.readBytes(swDescBytes);
134         String swDesc = new String(swDescBytes);
135         descBuilder.setSwDesc(swDesc.trim());
136         byte[] serialNumBytes = new byte[SERIAL_NUM_LEN];
137         input.readBytes(serialNumBytes);
138         String serialNum = new String(serialNumBytes);
139         descBuilder.setSerialNum(serialNum.trim());
140         byte[] dpDescBytes = new byte[DESC_STR_LEN];
141         input.readBytes(dpDescBytes);
142         String dpDesc = new String(dpDescBytes);
143         descBuilder.setDpDesc(dpDesc.trim());
144         caseBuilder.setMultipartReplyDesc(descBuilder.build());
145         return caseBuilder.build();
146     }
147
148     private MultipartReplyFlowCase setFlow(ByteBuf input) {
149         MultipartReplyFlowCaseBuilder caseBuilder = new MultipartReplyFlowCaseBuilder();
150         MultipartReplyFlowBuilder flowBuilder = new MultipartReplyFlowBuilder();
151         List<FlowStats> flowStatsList = new ArrayList<>();
152         while (input.readableBytes() > 0) {
153             FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder();
154             int length = input.readUnsignedShort();
155             flowStatsBuilder.setTableId(input.readUnsignedByte());
156             input.skipBytes(PADDING_IN_FLOW_STATS_HEADER);
157             OFDeserializer<MatchV10> matchDeserializer = registry.getDeserializer(
158                     new MessageCodeKey(EncodeConstants.OF10_VERSION_ID, EncodeConstants.EMPTY_VALUE, MatchV10.class));
159             flowStatsBuilder.setMatchV10(matchDeserializer.deserialize(input));
160             flowStatsBuilder.setDurationSec(input.readUnsignedInt());
161             flowStatsBuilder.setDurationNsec(input.readUnsignedInt());
162             flowStatsBuilder.setPriority(input.readUnsignedShort());
163             flowStatsBuilder.setIdleTimeout(input.readUnsignedShort());
164             flowStatsBuilder.setHardTimeout(input.readUnsignedShort());
165             input.skipBytes(PADDING_IN_FLOW_STATS_HEADER_02);
166             byte[] cookie = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
167             input.readBytes(cookie);
168             flowStatsBuilder.setCookie(new BigInteger(1, cookie));
169             byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
170             input.readBytes(packetCount);
171             flowStatsBuilder.setPacketCount(new BigInteger(1, packetCount));
172             byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
173             input.readBytes(byteCount);
174             flowStatsBuilder.setByteCount(new BigInteger(1, byteCount));
175             CodeKeyMaker keyMaker = CodeKeyMakerFactory.createActionsKeyMaker(EncodeConstants.OF10_VERSION_ID);
176             List<Action> actions = ListDeserializer.deserializeList(EncodeConstants.OF10_VERSION_ID,
177                     length - LENGTH_OF_FLOW_STATS, input, keyMaker, registry);
178             flowStatsBuilder.setAction(actions);
179             flowStatsList.add(flowStatsBuilder.build());
180         }
181         flowBuilder.setFlowStats(flowStatsList);
182         caseBuilder.setMultipartReplyFlow(flowBuilder.build());
183         return caseBuilder.build();
184     }
185
186     private static MultipartReplyAggregateCase setAggregate(ByteBuf input) {
187         MultipartReplyAggregateCaseBuilder caseBuilder = new MultipartReplyAggregateCaseBuilder();
188         MultipartReplyAggregateBuilder builder = new MultipartReplyAggregateBuilder();
189         byte[] packetCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
190         input.readBytes(packetCount);
191         builder.setPacketCount(new BigInteger(1, packetCount));
192         byte[] byteCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
193         input.readBytes(byteCount);
194         builder.setByteCount(new BigInteger(1, byteCount));
195         builder.setFlowCount(input.readUnsignedInt());
196         input.skipBytes(PADDING_IN_AGGREGATE_HEADER);
197         caseBuilder.setMultipartReplyAggregate(builder.build());
198         return caseBuilder.build();
199     }
200
201     private static MultipartReplyTableCase setTable(ByteBuf input) {
202         MultipartReplyTableCaseBuilder caseBuilder = new MultipartReplyTableCaseBuilder();
203         MultipartReplyTableBuilder builder = new MultipartReplyTableBuilder();
204         List<TableStats> tableStatsList = new ArrayList<>();
205         // TODO - replace ">= TABLE_STATS_LENGTH" with "> 0" after fix in OVS switch
206         while (input.readableBytes() >= TABLE_STATS_LENGTH) {
207             TableStatsBuilder tableStatsBuilder = new TableStatsBuilder();
208             tableStatsBuilder.setTableId(input.readUnsignedByte());
209             input.skipBytes(PADDING_IN_TABLE_HEADER);
210             tableStatsBuilder.setName(ByteBufUtils.decodeNullTerminatedString(input, MAX_TABLE_NAME_LENGTH));
211             long wildcards = input.readUnsignedInt();
212             tableStatsBuilder.setWildcards(OF10MatchDeserializer.createWildcards(wildcards));
213             tableStatsBuilder.setNwSrcMask(OF10MatchDeserializer.decodeNwSrcMask(wildcards));
214             tableStatsBuilder.setNwDstMask(OF10MatchDeserializer.decodeNwDstMask(wildcards));
215             tableStatsBuilder.setMaxEntries(input.readUnsignedInt());
216             tableStatsBuilder.setActiveCount(input.readUnsignedInt());
217             byte[] lookupCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
218             input.readBytes(lookupCount);
219             tableStatsBuilder.setLookupCount(new BigInteger(1, lookupCount));
220             byte[] matchedCount = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
221             input.readBytes(matchedCount);
222             tableStatsBuilder.setMatchedCount(new BigInteger(1, matchedCount));
223             tableStatsList.add(tableStatsBuilder.build());
224         }
225         input.skipBytes(input.readableBytes());
226         builder.setTableStats(tableStatsList);
227         caseBuilder.setMultipartReplyTable(builder.build());
228         return caseBuilder.build();
229     }
230
231     private static MultipartReplyPortStatsCase setPortStats(ByteBuf input) {
232         MultipartReplyPortStatsCaseBuilder caseBuilder = new MultipartReplyPortStatsCaseBuilder();
233         MultipartReplyPortStatsBuilder builder = new MultipartReplyPortStatsBuilder();
234         List<PortStats> portStatsList = new ArrayList<>();
235         while (input.readableBytes() > 0) {
236             PortStatsBuilder portStatsBuilder = new PortStatsBuilder();
237             portStatsBuilder.setPortNo((long) input.readUnsignedShort());
238             input.skipBytes(PADDING_IN_PORT_STATS_HEADER);
239             byte[] rxPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
240             input.readBytes(rxPackets);
241             portStatsBuilder.setRxPackets(new BigInteger(1, rxPackets));
242             byte[] txPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
243             input.readBytes(txPackets);
244             portStatsBuilder.setTxPackets(new BigInteger(1, txPackets));
245             byte[] rxBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
246             input.readBytes(rxBytes);
247             portStatsBuilder.setRxBytes(new BigInteger(1, rxBytes));
248             byte[] txBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
249             input.readBytes(txBytes);
250             portStatsBuilder.setTxBytes(new BigInteger(1, txBytes));
251             byte[] rxDropped = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
252             input.readBytes(rxDropped);
253             portStatsBuilder.setRxDropped(new BigInteger(1, rxDropped));
254             byte[] txDropped = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
255             input.readBytes(txDropped);
256             portStatsBuilder.setTxDropped(new BigInteger(1, txDropped));
257             byte[] rxErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
258             input.readBytes(rxErrors);
259             portStatsBuilder.setRxErrors(new BigInteger(1, rxErrors));
260             byte[] txErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
261             input.readBytes(txErrors);
262             portStatsBuilder.setTxErrors(new BigInteger(1, txErrors));
263             byte[] rxFrameErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
264             input.readBytes(rxFrameErr);
265             portStatsBuilder.setRxFrameErr(new BigInteger(1, rxFrameErr));
266             byte[] rxOverErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
267             input.readBytes(rxOverErr);
268             portStatsBuilder.setRxOverErr(new BigInteger(1, rxOverErr));
269             byte[] rxCrcErr = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
270             input.readBytes(rxCrcErr);
271             portStatsBuilder.setRxCrcErr(new BigInteger(1, rxCrcErr));
272             byte[] collisions = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
273             input.readBytes(collisions);
274             portStatsBuilder.setCollisions(new BigInteger(1, collisions));
275             portStatsList.add(portStatsBuilder.build());
276         }
277         builder.setPortStats(portStatsList);
278         caseBuilder.setMultipartReplyPortStats(builder.build());
279         return caseBuilder.build();
280     }
281
282     private static MultipartReplyQueueCase setQueue(ByteBuf input) {
283         MultipartReplyQueueCaseBuilder caseBuilder = new MultipartReplyQueueCaseBuilder();
284         MultipartReplyQueueBuilder builder = new MultipartReplyQueueBuilder();
285         List<QueueStats> queueStatsList = new ArrayList<>();
286         while (input.readableBytes() > 0) {
287             QueueStatsBuilder queueStatsBuilder = new QueueStatsBuilder();
288             queueStatsBuilder.setPortNo((long) input.readUnsignedShort());
289             input.skipBytes(PADDING_IN_QUEUE_HEADER);
290             queueStatsBuilder.setQueueId(input.readUnsignedInt());
291             byte[] txBytes = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
292             input.readBytes(txBytes);
293             queueStatsBuilder.setTxBytes(new BigInteger(1, txBytes));
294             byte[] txPackets = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
295             input.readBytes(txPackets);
296             queueStatsBuilder.setTxPackets(new BigInteger(1, txPackets));
297             byte[] txErrors = new byte[EncodeConstants.SIZE_OF_LONG_IN_BYTES];
298             input.readBytes(txErrors);
299             queueStatsBuilder.setTxErrors(new BigInteger(1, txErrors));
300             queueStatsList.add(queueStatsBuilder.build());
301         }
302         builder.setQueueStats(queueStatsList);
303         caseBuilder.setMultipartReplyQueue(builder.build());
304         return caseBuilder.build();
305     }
306
307     private MultipartReplyExperimenterCase setExperimenter(ByteBuf input) {
308         final long expId = input.readUnsignedInt();
309         final OFDeserializer<ExperimenterDataOfChoice> deserializer = registry.getDeserializer(ExperimenterDeserializerKeyFactory.createMultipartReplyVendorMessageDeserializerKey(
310                 EncodeConstants.OF10_VERSION_ID, expId));
311
312         final MultipartReplyExperimenterBuilder mpExperimenterBld = new MultipartReplyExperimenterBuilder()
313                 .setExperimenter(new ExperimenterId(expId))
314                 .setExperimenterDataOfChoice(deserializer.deserialize(input));
315         final MultipartReplyExperimenterCaseBuilder mpReplyExperimenterCaseBld = new MultipartReplyExperimenterCaseBuilder()
316                 .setMultipartReplyExperimenter(mpExperimenterBld.build());
317         return mpReplyExperimenterCaseBld.build();
318     }
319
320     @Override
321     public void injectDeserializerRegistry(DeserializerRegistry deserializerRegistry) {
322         registry = deserializerRegistry;
323     }
324 }