Reducing duplication in `TryFrom`

Hey folks,

I've got the following duplication:

impl TryFrom<Reader<&[u8]>> for DictionaryStemmer {
    type Error = Error;

    fn try_from(mut reader: Reader<&[u8]>) -> Result<Self, Self::Error> {
        let mut term_stems: HashMap<String, String> = HashMap::new();
        for record in reader.deserialize() {
            let term_stem: TermStem = record?;
            if let Some(stem) = term_stem.dpd_stem {
                term_stems.insert(term_stem.term, stem);
            }
        }
        Ok(Self { term_stems })
    }
}

impl TryFrom<Reader<File>> for DictionaryStemmer {
    type Error = Error;

    fn try_from(mut reader: Reader<File>) -> Result<Self, Self::Error> {
        let mut term_stems: HashMap<String, String> = HashMap::new();
        for record in reader.deserialize() {
            let term_stem: TermStem = record?;
            if let Some(stem) = term_stem.dpd_stem {
                term_stems.insert(term_stem.term, stem);
            }
        }
        Ok(Self { term_stems })
    }
}

Is there a way to combine these into one impl TryFrom ?

Thanks again!

Use generic, then limit the type with marker trait

For example

trait CanProcess {}

struct ObjectA
struct ObjectB

impl CanProcess for ObjectA {}
impl CanProcess for ObjectB {}

struct Reader<T>(T)

struct Error
struct Input

impl<T> TryFrom<Reader<T>> for Input
where
    T: CanProcess
{
    type Error = Error

    fn try_from(reader: Reader<T>) -> Result<Self, Self::Error> {
        ....
    }
}

Ahah!

The resulting implementation looks like this:

impl<T> TryFrom<Reader<T>> for DictionaryStemmer
where T: std::io::Read
{
    type Error = Error;

    fn try_from(mut reader: Reader<T>) -> Result<Self, Self::Error> {
        let mut term_stems: HashMap<String, String> = HashMap::new();
        for record in reader.deserialize() {
            let term_stem: TermStem = record?;
            if let Some(stem) = term_stem.dpd_stem {
                term_stems.insert(term_stem.term, stem);
            }
        }
        Ok(Self { term_stems })
    }
}