Is there a way to prevent try_from from consuming a mutable reference?

I have a struct

struct Triangle {
    normal: Normal,
    vertices: [Vertex; 3],
}

that I’d like to deserialize from a Read type. I thought implementing TryFrom would be idiomatic since I’m turning a stream of bytes into a Triangle but it may fail.

impl TryFrom<&mut dyn std::io::Read> for Triangle {
  type Error = std::io::Error;
  fn try_from(reader: &mut dyn std::io::Read) -> Result<Self, Self::Error> {
    Ok(Self {
        normal: Normal::try_from(reader)?,
        vertices: [Vertex::try_from(reader)?, Vertex::try_from(reader)?, Vertex::try_from(reader)?]
    })
  }
}

I believe I could shove all of the usage of the reader : &mut Read into the Triangle implementation but

  1. I like having the parsing for an object in its own impl and
  2. I’ll just run into the same problem when I try to parse multiple Triangles to build a mesh

I’m starting to get the feeling that implementing TryFrom is the wrong approach here but before I gave up I thought I’d ask if there was a clean way to let Normal::try_From borrow the reader then let Vertex::try_from borrow the reader while following ownership rules.

Here is a full listing of the module: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d79881fee912acf0fa4496f90a34df86

(I know that STL has a u16 attribute after each triangle, just haven’t gotten around to it yet)

>Solution :

You can fully qualify the call, although it is not obvious to me why it doesn’t compile in the first place:

impl TryFrom<&mut dyn std::io::Read> for Triangle {
    type Error = std::io::Error;
    fn try_from(reader: &mut dyn std::io::Read) -> Result<Self, Self::Error> {
        Ok(Self {
            normal: <Normal as TryFrom<&mut dyn std::io::Read>>::try_from(reader)?,
            vertices: [
                <Vertex as TryFrom<&mut dyn std::io::Read>>::try_from(reader)?,
                <Vertex as TryFrom<&mut dyn std::io::Read>>::try_from(reader)?,
                Vertex::try_from(reader)?,
            ],
        })
    }
}

But I’d just implement a custom method.

Leave a Reply