1use crate::error::{DecodeError, OpResult, StackError};
2use essential_types::Word;
3
4#[cfg(test)]
5mod tests;
6
7#[cfg(test)]
8pub(crate) fn encode_set<S, I>(set: S, stack: &mut crate::Stack) -> OpResult<()>
10where
11 I: ExactSizeIterator<Item = Word>,
12 S: ExactSizeIterator<Item = I>,
13{
14 let mut len = set.len();
15 for item in set {
16 let item_len = item.len();
17 len = len
18 .checked_add(item_len)
19 .ok_or(crate::error::EncodeError::ItemLengthTooLarge(len))?;
20 stack.extend(item)?;
21 stack.push(
22 item_len
23 .try_into()
24 .map_err(|_| crate::error::EncodeError::ItemLengthTooLarge(item_len))?,
25 )?;
26 }
27 stack.push(
28 len.try_into()
29 .map_err(|_| crate::error::EncodeError::ItemLengthTooLarge(len))?,
30 )?;
31 Ok(())
32}
33
34pub(crate) fn decode_set(words: &[Word]) -> impl '_ + Iterator<Item = OpResult<&[Word]>> {
36 let mut ws = words;
37 std::iter::from_fn(move || {
38 let (len, rest) = ws.split_last()?;
39 let ix = match usize::try_from(*len)
40 .map_err(|_| StackError::Overflow.into())
41 .and_then(|len| {
42 rest.len()
43 .checked_sub(len)
44 .ok_or_else(|| DecodeError::Set(words.to_vec()).into())
45 }) {
46 Ok(ix) => ix,
47 Err(e) => return Some(Err(e)),
48 };
49 let (rest, key) = rest.split_at(ix);
50 ws = rest;
51 Some(Ok(key))
52 })
53}