Skip to main content

ldap_client_ber/
length.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use crate::BerError;
4
5/// Encode a definite length in minimal BER form.
6pub fn encode_length(len: usize) -> Vec<u8> {
7    if len < 0x80 {
8        return vec![len as u8];
9    }
10    let be = len.to_be_bytes();
11    let start = be.iter().position(|&b| b != 0).unwrap_or(be.len() - 1);
12    let num_bytes = be.len() - start;
13    let mut result = Vec::with_capacity(1 + num_bytes);
14    result.push(0x80 | num_bytes as u8);
15    result.extend_from_slice(&be[start..]);
16    result
17}
18
19/// Decode a BER length field. Returns `(length_field_size, value_length)`.
20///
21/// Returns `None` if more data is needed.
22/// Returns `Err` for invalid encodings (indefinite length, overflow).
23pub fn decode_length(input: &[u8]) -> Result<Option<(usize, usize)>, BerError> {
24    if input.is_empty() {
25        return Ok(None);
26    }
27
28    let first = input[0];
29    if first == 0x80 {
30        return Err(BerError::IndefiniteLength);
31    }
32
33    if first < 0x80 {
34        return Ok(Some((1, first as usize)));
35    }
36
37    let num_bytes = (first & 0x7F) as usize;
38    if num_bytes > 4 {
39        return Err(BerError::InvalidLength);
40    }
41    if input.len() < 1 + num_bytes {
42        return Ok(None);
43    }
44
45    let mut length: u64 = 0;
46    for &b in &input[1..1 + num_bytes] {
47        length = (length << 8) | b as u64;
48    }
49
50    // Guard against overflow before casting to usize.
51    if length > usize::MAX as u64 {
52        return Err(BerError::ElementTooLarge {
53            size: length,
54            max: u32::MAX,
55        });
56    }
57
58    Ok(Some((1 + num_bytes, length as usize)))
59}