eclisp 0.2.0-beta.0

Bindings for Embeddable Common Lisp
use crate::{LispContext, LispError, Value, ValueRef};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ObjectId {
    pub(super) index: usize,
    pub(super) generation: u64,
}

impl ObjectId {
    pub fn index(self) -> usize {
        self.index
    }

    pub fn generation(self) -> u64 {
        self.generation
    }

    pub fn to_lisp<'rt>(self, ctx: &LispContext<'rt>) -> Result<Value<'rt>, LispError> {
        let index = i64::try_from(self.index)
            .map_err(|_| LispError::RuntimeError("Object index overflow".into()))?;

        let generation = i64::try_from(self.generation)
            .map_err(|_| LispError::RuntimeError("Object generation overflow".into()))?;

        let index = ctx.int(index)?;
        let generation = ctx.int(generation)?;

        ctx.list(&[&index, &generation])
    }

    pub fn from_lisp(value: ValueRef<'_>) -> Result<Self, LispError> {
        if value.len()? != 2 {
            return Err(LispError::RuntimeError(
                "Object handle must contain two integers".into(),
            ));
        }

        let index = value.nth(0)?.unwrap().try_as_i64()?;
        let generation = value.nth(1)?.unwrap().try_as_i64()?;

        let index = usize::try_from(index)
            .map_err(|_| LispError::RuntimeError("Invalid object index".into()))?;

        let generation = u64::try_from(generation)
            .map_err(|_| LispError::RuntimeError("Invalid object generation".into()))?;

        Ok(Self { index, generation })
    }
}