• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2##########################################################
3#                                                        #
4#  __          __     _____  _   _ _____ _   _  _____    #
5#  \ \        / /\   |  __ \| \ | |_   _| \ | |/ ____|   #
6#   \ \  /\  / /  \  | |__) |  \| | | | |  \| | |  __    #
7#    \ \/  \/ / /\ \ |  _  /| . ` | | | | . ` | | |_ |   #
8#     \  /\  / ____ \| | \ \| |\  |_| |_| |\  | |__| |   #
9#      \/  \/_/    \_\_|  \_\_| \_|_____|_| \_|\_____|   #
10#                                                        #
11#                                                        #
12##########################################################
13# Do not use this class in your code. This class purely  #
14# exists to make proto code generation easier.           #
15##########################################################
16*/
17goog.module('protobuf.runtime.MessageSet');
18
19const InternalMessage = goog.require('protobuf.binary.InternalMessage');
20const Kernel = goog.require('protobuf.runtime.Kernel');
21
22// These are the tags for the old MessageSet format, which was defined as:
23//   message MessageSet {
24//     repeated group Item = 1 {
25//       required uint32 type_id = 2;
26//       optional bytes message = 3;
27//     }
28//   }
29/** @const {number} */
30const MSET_GROUP_FIELD_NUMBER = 1;
31/** @const {number} */
32const MSET_TYPE_ID_FIELD_NUMBER = 2;
33/** @const {number} */
34const MSET_MESSAGE_FIELD_NUMBER = 3;
35
36/**
37 * @param {!Kernel} kernel
38 * @return {!Map<number, !Item>}
39 */
40function createItemMap(kernel) {
41  const itemMap = new Map();
42  let totalCount = 0;
43  for (const item of kernel.getRepeatedGroupIterable(
44           MSET_GROUP_FIELD_NUMBER, Item.fromKernel)) {
45    itemMap.set(item.getTypeId(), item);
46    totalCount++;
47  }
48
49  // Normalize the entries.
50  if (totalCount > itemMap.size) {
51    writeItemMap(kernel, itemMap);
52  }
53  return itemMap;
54}
55
56/**
57 * @param {!Kernel} kernel
58 * @param {!Map<number, !Item>} itemMap
59 */
60function writeItemMap(kernel, itemMap) {
61  kernel.setRepeatedGroupIterable(MSET_GROUP_FIELD_NUMBER, itemMap.values());
62}
63
64/**
65 * @implements {InternalMessage}
66 * @final
67 */
68class MessageSet {
69  /**
70   * @param {!Kernel} kernel
71   * @return {!MessageSet}
72   */
73  static fromKernel(kernel) {
74    const itemMap = createItemMap(kernel);
75    return new MessageSet(kernel, itemMap);
76  }
77
78  /**
79   * @return {!MessageSet}
80   */
81  static createEmpty() {
82    return MessageSet.fromKernel(Kernel.createEmpty());
83  }
84
85  /**
86   * @param {!Kernel} kernel
87   * @param {!Map<number, !Item>} itemMap
88   * @private
89   */
90  constructor(kernel, itemMap) {
91    /** @const {!Kernel} @private */
92    this.kernel_ = kernel;
93    /** @const {!Map<number, !Item>} @private */
94    this.itemMap_ = itemMap;
95  }
96
97
98
99  // code helpers for code gen
100
101  /**
102   * @param {number} typeId
103   * @param {function(!Kernel):T} instanceCreator
104   * @param {number=} pivot
105   * @return {?T}
106   * @template T
107   */
108  getMessageOrNull(typeId, instanceCreator, pivot) {
109    const item = this.itemMap_.get(typeId);
110    return item ? item.getMessageOrNull(instanceCreator, pivot) : null;
111  }
112
113  /**
114   * @param {number} typeId
115   * @param {function(!Kernel):T} instanceCreator
116   * @param {number=} pivot
117   * @return {T}
118   * @template T
119   */
120  getMessageAttach(typeId, instanceCreator, pivot) {
121    let item = this.itemMap_.get(typeId);
122    if (item) {
123      return item.getMessageAttach(instanceCreator, pivot);
124    }
125    const message = instanceCreator(Kernel.createEmpty());
126    this.setMessage(typeId, message);
127    return message;
128  }
129
130  /**
131   * @param {number} typeId
132   * @param {number=} pivot
133   * @return {?Kernel}
134   */
135  getMessageAccessorOrNull(typeId, pivot) {
136    const item = this.itemMap_.get(typeId);
137    return item ? item.getMessageAccessorOrNull(pivot) : null;
138  }
139
140
141  /**
142   * @param {number} typeId
143   */
144  clearMessage(typeId) {
145    if (this.itemMap_.delete(typeId)) {
146      writeItemMap(this.kernel_, this.itemMap_);
147    }
148  }
149
150  /**
151   * @param {number} typeId
152   * @return {boolean}
153   */
154  hasMessage(typeId) {
155    return this.itemMap_.has(typeId);
156  }
157
158  /**
159   * @param {number} typeId
160   * @param {!InternalMessage} value
161   */
162  setMessage(typeId, value) {
163    const item = this.itemMap_.get(typeId);
164    if (item) {
165      item.setMessage(value);
166    } else {
167      this.itemMap_.set(typeId, Item.create(typeId, value));
168      writeItemMap(this.kernel_, this.itemMap_);
169    }
170  }
171
172  /**
173   * @return {!Kernel}
174   * @override
175   */
176  internalGetKernel() {
177    return this.kernel_;
178  }
179}
180
181/**
182 * @implements {InternalMessage}
183 * @final
184 */
185class Item {
186  /**
187   * @param {number} typeId
188   * @param {!InternalMessage} message
189   * @return {!Item}
190   */
191  static create(typeId, message) {
192    const messageSet = Item.fromKernel(Kernel.createEmpty());
193    messageSet.setTypeId_(typeId);
194    messageSet.setMessage(message);
195    return messageSet;
196  }
197
198
199  /**
200   * @param {!Kernel} kernel
201   * @return {!Item}
202   */
203  static fromKernel(kernel) {
204    return new Item(kernel);
205  }
206
207  /**
208   * @param {!Kernel} kernel
209   * @private
210   */
211  constructor(kernel) {
212    /** @const {!Kernel} @private */
213    this.kernel_ = kernel;
214  }
215
216  /**
217   * @param {function(!Kernel):T} instanceCreator
218   * @param {number=} pivot
219   * @return {T}
220   * @template T
221   */
222  getMessage(instanceCreator, pivot) {
223    return this.kernel_.getMessage(
224        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
225  }
226
227  /**
228   * @param {function(!Kernel):T} instanceCreator
229   * @param {number=} pivot
230   * @return {?T}
231   * @template T
232   */
233  getMessageOrNull(instanceCreator, pivot) {
234    return this.kernel_.getMessageOrNull(
235        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
236  }
237
238  /**
239   * @param {function(!Kernel):T} instanceCreator
240   * @param {number=} pivot
241   * @return {T}
242   * @template T
243   */
244  getMessageAttach(instanceCreator, pivot) {
245    return this.kernel_.getMessageAttach(
246        MSET_MESSAGE_FIELD_NUMBER, instanceCreator, pivot);
247  }
248
249  /**
250   * @param {number=} pivot
251   * @return {?Kernel}
252   */
253  getMessageAccessorOrNull(pivot) {
254    return this.kernel_.getMessageAccessorOrNull(
255        MSET_MESSAGE_FIELD_NUMBER, pivot);
256  }
257
258  /** @param {!InternalMessage} value */
259  setMessage(value) {
260    this.kernel_.setMessage(MSET_MESSAGE_FIELD_NUMBER, value);
261  }
262
263  /** @return {number} */
264  getTypeId() {
265    return this.kernel_.getUint32WithDefault(MSET_TYPE_ID_FIELD_NUMBER);
266  }
267
268  /**
269   * @param {number} value
270   * @private
271   */
272  setTypeId_(value) {
273    this.kernel_.setUint32(MSET_TYPE_ID_FIELD_NUMBER, value);
274  }
275
276  /**
277   * @return {!Kernel}
278   * @override
279   */
280  internalGetKernel() {
281    return this.kernel_;
282  }
283}
284
285exports = MessageSet;
286