| 205 | } |
| 206 | |
| 207 | func (c *MultirangeCodec) decodeBinary(m *Map, multirangeOID uint32, src []byte, multirange MultirangeSetter) error { |
| 208 | rp := 0 |
| 209 | |
| 210 | elementCount := int(binary.BigEndian.Uint32(src[rp:])) |
| 211 | rp += 4 |
| 212 | |
| 213 | // Each element requires at least 4 bytes for its length prefix. |
| 214 | if elementCount > len(src)/4 { |
| 215 | return fmt.Errorf("multirange element count %d exceeds available data", elementCount) |
| 216 | } |
| 217 | |
| 218 | err := multirange.SetLen(elementCount) |
| 219 | if err != nil { |
| 220 | return err |
| 221 | } |
| 222 | |
| 223 | if elementCount == 0 { |
| 224 | return nil |
| 225 | } |
| 226 | |
| 227 | elementScanPlan := c.ElementType.Codec.PlanScan(m, c.ElementType.OID, BinaryFormatCode, multirange.ScanIndex(0)) |
| 228 | if elementScanPlan == nil { |
| 229 | elementScanPlan = m.PlanScan(c.ElementType.OID, BinaryFormatCode, multirange.ScanIndex(0)) |
| 230 | } |
| 231 | |
| 232 | for i := range elementCount { |
| 233 | elem := multirange.ScanIndex(i) |
| 234 | if len(src[rp:]) < 4 { |
| 235 | return fmt.Errorf("multirange body truncated at element %d", i) |
| 236 | } |
| 237 | elemLen := int(int32(binary.BigEndian.Uint32(src[rp:]))) |
| 238 | rp += 4 |
| 239 | var elemSrc []byte |
| 240 | if elemLen >= 0 { |
| 241 | if len(src[rp:]) < elemLen { |
| 242 | return fmt.Errorf("multirange element %d length %d exceeds remaining %d bytes", i, elemLen, len(src[rp:])) |
| 243 | } |
| 244 | elemSrc = src[rp : rp+elemLen] |
| 245 | rp += elemLen |
| 246 | } |
| 247 | err = elementScanPlan.Scan(elemSrc, elem) |
| 248 | if err != nil { |
| 249 | return fmt.Errorf("failed to scan multirange element %d: %w", i, err) |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | return nil |
| 254 | } |
| 255 | |
| 256 | func (c *MultirangeCodec) decodeText(m *Map, multirangeOID uint32, src []byte, multirange MultirangeSetter) error { |
| 257 | elements, err := parseUntypedTextMultirange(src) |