Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement Serialize and Deserialize #133

Open
dzmitry-lahoda opened this issue Apr 1, 2024 · 7 comments
Open

feat: implement Serialize and Deserialize #133

dzmitry-lahoda opened this issue Apr 1, 2024 · 7 comments
Labels
good first issue Good for newcomers

Comments

@dzmitry-lahoda
Copy link

dzmitry-lahoda commented Apr 1, 2024

All the different ringbuffers should implement Serialize and Deserialize when the serde feature is enabled, and should do so safely and soundly.

@dzmitry-lahoda
Copy link
Author

@jdonszelmann would PR with borsh serde considered for review and merge if made? behind borsh feature gate

@jdonszelmann
Copy link
Collaborator

I like the idea, but why do we need borsh? I think if you implement the Serialize and Deserialize traits that should be enough. Then you can choose any format (like postcard or even json if you really wanted)

@jdonszelmann
Copy link
Collaborator

I talked to @NULLx76 about this and we'd prefer serde to borsh

@NULLx76
Copy link
Owner

NULLx76 commented May 15, 2024

Additionally I'm against this because Borsh seems related to blockchain/web3 which is not something we'd like to condone

@jdonszelmann jdonszelmann added the good first issue Good for newcomers label May 15, 2024
@jdonszelmann
Copy link
Collaborator

Feel free to file a PR though

@jdonszelmann jdonszelmann changed the title feat: impl some serde feat: implement Serialize and Deserialize May 15, 2024
@dzmitry-lahoda
Copy link
Author

dzmitry-lahoda commented May 19, 2024

please reopen when change reasoning.

here is wrapper for Const if somebody needs that

//! This module provides serialization and deserialization for the `ringbuffer` crate.
use borsh::{BorshDeserialize, BorshSerialize};
use ringbuffer::{ConstGenericRingBuffer, RingBuffer};

#[derive(Debug, Default, BorshSerialize, BorshDeserialize, Clone)]
pub struct ConstGenericRingBufferWrapper<T, const CAP: usize> {
    #[borsh(
        serialize_with = "serialize_const_generic_ring_buffer",
        deserialize_with = "deserialize_const_generic_ring_buffer"
    )]
    buffer: ConstGenericRingBuffer<T, CAP>,
}

/// Ring buffer is just fixed size array
#[cfg(test)]
impl<T: borsh::BorshSchema, const CAP: usize> borsh::BorshSchema
    for ConstGenericRingBufferWrapper<T, CAP>
{
    fn add_definitions_recursively(
        definitions: &mut std::collections::BTreeMap<
            borsh::schema::Declaration,
            borsh::schema::Definition,
        >,
    ) {
        <[T; CAP]>::add_definitions_recursively(definitions)
    }

    fn declaration() -> borsh::schema::Declaration {
        <[T; CAP]>::declaration()
    }
}

impl<T, const CAP: usize> ConstGenericRingBufferWrapper<T, CAP> {
    pub fn peek(&self) -> Option<&T> {
        self.buffer.peek()
    }

    pub fn push(&mut self, item: T) {
        self.buffer.push(item);
    }

    pub fn back(&self) -> Option<&T> {
        self.buffer.back()
    }

    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.buffer.iter()
    }

    pub fn get(&self, index: usize) -> Option<&T> {
        self.buffer.get(index)
    }

    pub fn len(&self) -> usize {
        self.buffer.len()
    }

    pub fn front(&self) -> Option<&T> {
        self.buffer.front()
    }
}

pub fn serialize_const_generic_ring_buffer<T: borsh::BorshSerialize, const CAP: usize>(
    obj: &ConstGenericRingBuffer<T, CAP>,
    writer: &mut impl std::io::prelude::Write,
) -> std::io::Result<()> {
    for item in obj.into_iter() {
        item.serialize(writer)?;
    }
    Ok(())
}

pub fn deserialize_const_generic_ring_buffer<T: borsh::BorshDeserialize, const CAP: usize>(
    reader: &mut impl std::io::prelude::Read,
) -> std::io::Result<ConstGenericRingBuffer<T, CAP>> {
    let mut buffer = ConstGenericRingBuffer::new();
    for _ in 0..CAP {
        buffer.push(T::try_from_reader(reader)?);
    }
    if T::try_from_reader(reader).is_ok() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            "Buffer is longs than CAP",
        ));
    }
    Ok(buffer)
}

@dzmitry-lahoda
Copy link
Author

sorry, some mix of things. closed for borsh. for serde open sure :) sorry for confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

3 participants