How to convert nom::Context<&[u8]> to Context<MyErrorKind>


#1

Hello.

I need some help.

The story is

pub struct DeserializeError {
    ctx: Context<MyErrorKind>,
}
impl DeserializeError {
    /// Return the kind of this error.
    pub fn kind(&self) -> &MyErrorKind {
        self.ctx.get_context()
    }

    pub(crate) fn incomplete(needed: Needed, data: Vec<u8>) -> DeserializeError {
        DeserializeError::from(MyErrorKind::IncompleteData { needed, data })
    }

    pub(crate) fn deserialize(error: nom::Context<&[u8]>, data: Vec<u8>) -> DeserializeError {
        DeserializeError::from(MyErrorKind::Deserialize { error, data })
    }
}

pub enum MyErrorKind {
    /// Error indicates that object can't be parsed.
    Deserialize {
        /// Parsing error
        error: nom::Context<&'static[u8]>,
        /// Object serialized data
        data: Vec<u8>,
    },
    /// Error indicates that more data is needed to parse serialized object.
    IncompleteData {
        /// Required data size to be parsed
        needed: Needed,
        /// Object serialized data
        data: Vec<u8>,
    },
}

 let nodes = match DhtState::from_bytes(serialized_data) {
            Ok((_, DhtState(nodes))) => nodes,
            Err(Err::Incomplete(needed)) =>
                return Either::A(future::err(DeserializeError::incomplete(needed, serialized_data.to_vec()))),
            Err(Err::Error(error)) =>
                return Either::A(future::err(DeserializeError::deserialize(error, serialized_data.to_vec()))),
        };

the error type of nom parser is nom::Context<&[u8]> and I have to convert it to Context<MyErrorKind>. Is it right?

If so, how to convert it.

In failure docs, there is a mention which says that implement From<u8>. But I can’t see what should I do.

Thanks in advance.


#2

The context refers to the string/buffer being parsed, not the error type.

It’s usually a non-static reference (&'static will let you only parse string literals, and nothing else), so to put it in your error type you’d need to also tie your error type to the input string reference (MyErrorKind<'a>).

Note that you can’t store the data and reference to the data in the same struct. Self-referential structs are not safe, and borrow checker doesn’t allow them in any way.

In practice I recommend e.into_error_kind() to get rid of the context, or even e.to_string().

If you really want to have the error with the context that refers to the copy of the data in the error, you can’t use nom's type. Make your own, and use integer indexes instead of references.


#3

Thank you. Very helpful.