| 198 | } |
| 199 | |
| 200 | func (e *Encoder) EncodeMap(mes []*MapEntryEncoder) error { |
| 201 | // Major type 5: a map of pairs of data items. Maps are also called |
| 202 | // tables, dictionaries, hashes, or objects (in JSON). A map is |
| 203 | // comprised of pairs of data items, each pair consisting of a key |
| 204 | // that is immediately followed by a value. The map's length follows |
| 205 | // the rules for byte strings (major type 2), except that the length |
| 206 | // denotes the number of pairs, not the length in bytes that the map |
| 207 | // takes up. For example, a map that contains 9 pairs would have an |
| 208 | // initial byte of 0b101_01001 (major type of 5, additional |
| 209 | // information of 9 for the number of pairs) followed by the 18 |
| 210 | // remaining items. The first item is the first key, the second item |
| 211 | // is the first value, the third item is the second key, and so on. |
| 212 | // A map that has duplicate keys may be well-formed, but it is not |
| 213 | // valid, and thus it causes indeterminate decoding; see also |
| 214 | // Section 3.7. |
| 215 | // |
| 216 | // https://tools.ietf.org/html/rfc7049#section-2.1 |
| 217 | |
| 218 | if err := e.encodeMapHeader(len(mes)); err != nil { |
| 219 | return err |
| 220 | } |
| 221 | |
| 222 | // Map keys must be sorted. Here copy all the keys into a slice for sorting. |
| 223 | // This is not very efficient, but it is expected that the number of keys is |
| 224 | // not so big in signedexchange usage. |
| 225 | entries := make([]*MapEntryEncoder, len(mes)) |
| 226 | copy(entries, mes) |
| 227 | sort.Slice(entries, func(i, j int) bool { |
| 228 | return bytes.Compare(entries[i].KeyBytes(), entries[j].KeyBytes()) < 0 |
| 229 | }) |
| 230 | |
| 231 | var lastKeyBytes []byte |
| 232 | for _, entry := range entries { |
| 233 | if lastKeyBytes != nil && bytes.Equal(lastKeyBytes, entry.KeyBytes()) { |
| 234 | return ErrDuplicatedKey |
| 235 | } |
| 236 | lastKeyBytes = entry.KeyBytes() |
| 237 | |
| 238 | if _, err := io.Copy(e.w, &entry.keyBuf); err != nil { |
| 239 | return err |
| 240 | } |
| 241 | if _, err := io.Copy(e.w, &entry.valueBuf); err != nil { |
| 242 | return err |
| 243 | } |
| 244 | } |
| 245 | return nil |
| 246 | } |