Encode a range type value PostgreSQL range binary format: - flags (1 byte): 0x01=empty, 0x02=LB_INC, 0x04=UB_INC, 0x08=LB_INF, 0x10=UB_INF - lower bound length + data (if not infinite) - upper bound length + data (if not infinite)
(range_str: &str)
| 423 | /// - lower bound length + data (if not infinite) |
| 424 | /// - upper bound length + data (if not infinite) |
| 425 | pub fn encode_int4range(range_str: &str) -> Result<Vec<u8>, String> { |
| 426 | let trimmed = range_str.trim(); |
| 427 | let mut result = Vec::new(); |
| 428 | |
| 429 | // Handle empty range |
| 430 | if trimmed == "empty" { |
| 431 | result.push(0x01); // RANGE_EMPTY flag |
| 432 | return Ok(result); |
| 433 | } |
| 434 | |
| 435 | // Parse range format: [lower,upper), (lower,upper], etc. |
| 436 | if trimmed.len() < 3 { |
| 437 | return Err("Invalid range format".to_string()); |
| 438 | } |
| 439 | |
| 440 | let lower_inclusive = trimmed.starts_with('['); |
| 441 | let upper_inclusive = trimmed.ends_with(']'); |
| 442 | |
| 443 | // Extract bounds |
| 444 | let inner = &trimmed[1..trimmed.len()-1]; |
| 445 | let parts: Vec<&str> = inner.split(',').collect(); |
| 446 | |
| 447 | if parts.len() != 2 { |
| 448 | return Err("Invalid range format: expected two bounds".to_string()); |
| 449 | } |
| 450 | |
| 451 | let lower_str = parts[0].trim(); |
| 452 | let upper_str = parts[1].trim(); |
| 453 | |
| 454 | // Calculate flags |
| 455 | let mut flags = 0u8; |
| 456 | if lower_inclusive { |
| 457 | flags |= 0x02; // LB_INC |
| 458 | } |
| 459 | if upper_inclusive { |
| 460 | flags |= 0x04; // UB_INC |
| 461 | } |
| 462 | |
| 463 | // Check for infinite bounds |
| 464 | let lower_infinite = lower_str == "-infinity" || lower_str.is_empty(); |
| 465 | let upper_infinite = upper_str == "infinity" || upper_str.is_empty(); |
| 466 | |
| 467 | if lower_infinite { |
| 468 | flags |= 0x08; // LB_INF |
| 469 | } |
| 470 | if upper_infinite { |
| 471 | flags |= 0x10; // UB_INF |
| 472 | } |
| 473 | |
| 474 | result.push(flags); |
| 475 | |
| 476 | // Encode lower bound if not infinite |
| 477 | if !lower_infinite { |
| 478 | let lower_val: i32 = lower_str.parse() |
| 479 | .map_err(|_| format!("Invalid lower bound: {lower_str}"))?; |
| 480 | let lower_bytes = lower_val.to_be_bytes(); |
| 481 | result.extend_from_slice(&(lower_bytes.len() as i32).to_be_bytes()); |
| 482 | result.extend_from_slice(&lower_bytes); |