libipld_core/
raw_value.rs

1//! misc stuff
2use alloc::{boxed::Box, vec, vec::Vec};
3use core::{convert::TryFrom, marker::PhantomData};
4
5use crate::codec::{Codec, Decode, Encode};
6use crate::io::{Read, Seek, SeekFrom, Write};
7
8/// A raw value for a certain codec.
9///
10/// Contains the raw, unprocessed data for a single item for that particular codec
11#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
12pub struct RawValue<C> {
13    data: Box<[u8]>,
14    _p: PhantomData<C>,
15}
16
17impl<C> RawValue<C> {
18    fn new(data: Box<[u8]>) -> Self {
19        Self {
20            data,
21            _p: PhantomData,
22        }
23    }
24}
25
26impl<C> AsRef<[u8]> for RawValue<C> {
27    fn as_ref(&self) -> &[u8] {
28        &self.data
29    }
30}
31
32impl<C> From<RawValue<C>> for Box<[u8]> {
33    fn from(value: RawValue<C>) -> Self {
34        value.data
35    }
36}
37
38impl<C> From<RawValue<C>> for Vec<u8> {
39    fn from(value: RawValue<C>) -> Self {
40        value.data.into()
41    }
42}
43
44/// trait to implement to skip a single item at the current position
45pub trait SkipOne: Codec {
46    /// assuming r is at the start of an item, advance r to the end
47    fn skip<R: Read + Seek>(&self, r: &mut R) -> anyhow::Result<()>;
48}
49
50impl<C: Codec + SkipOne> Decode<C> for RawValue<C> {
51    fn decode<R: Read + Seek>(c: C, r: &mut R) -> anyhow::Result<Self> {
52        let p0 = r.seek(SeekFrom::Current(0)).map_err(anyhow::Error::msg)?;
53        c.skip(r)?;
54        let p1 = r.seek(SeekFrom::Current(0)).map_err(anyhow::Error::msg)?;
55        // seeking backward is not allowed
56        anyhow::ensure!(p1 > p0);
57        // this will fail if usize is 4 bytes and an item is > 32 bit of length
58        let len = usize::try_from(p1 - p0).map_err(anyhow::Error::msg)?;
59        r.seek(SeekFrom::Start(p0)).map_err(anyhow::Error::msg)?;
60        let mut buf = vec![0u8; len];
61        r.read_exact(&mut buf).map_err(anyhow::Error::msg)?;
62        Ok(Self::new(buf.into()))
63    }
64}
65
66impl<C: Codec> Encode<C> for RawValue<C> {
67    fn encode<W: Write>(&self, _: C, w: &mut W) -> anyhow::Result<()> {
68        w.write_all(&self.data).map_err(anyhow::Error::msg)?;
69        Ok(())
70    }
71}
72
73/// Allows to ignore a single item
74#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
75pub struct IgnoredAny;
76
77impl<C: Codec + SkipOne> Decode<C> for IgnoredAny {
78    fn decode<R: Read + Seek>(c: C, r: &mut R) -> anyhow::Result<Self> {
79        c.skip(r)?;
80        Ok(Self)
81    }
82}