Skip to main content

shape_runtime/stdlib/
byte_utils.rs

1//! Shared byte array conversion utilities.
2//!
3//! Used by both `compress` and `archive` modules for converting between
4//! Shape's `Array<int>` representation and Rust `Vec<u8>`.
5
6use shape_value::ValueWord;
7use std::sync::Arc;
8
9/// Extract a byte array (`Array<int>`) from a ValueWord into a `Vec<u8>`.
10///
11/// Each array element must be an integer in the range 0..=255.
12pub fn bytes_from_array(val: &ValueWord) -> Result<Vec<u8>, String> {
13    let arr = val
14        .as_any_array()
15        .ok_or_else(|| "expected an Array<int> of bytes".to_string())?
16        .to_generic();
17    let mut bytes = Vec::with_capacity(arr.len());
18    for item in arr.iter() {
19        let byte_val = item
20            .as_i64()
21            .or_else(|| item.as_f64().map(|n| n as i64))
22            .ok_or_else(|| "array elements must be integers (0-255)".to_string())?;
23        if !(0..=255).contains(&byte_val) {
24            return Err(format!("byte value out of range: {}", byte_val));
25        }
26        bytes.push(byte_val as u8);
27    }
28    Ok(bytes)
29}
30
31/// Convert a `Vec<u8>` into a ValueWord `Array<int>`.
32pub fn bytes_to_array(bytes: &[u8]) -> ValueWord {
33    let items: Vec<ValueWord> = bytes
34        .iter()
35        .map(|&b| ValueWord::from_i64(b as i64))
36        .collect();
37    ValueWord::from_array(Arc::new(items))
38}