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