Skip to content
This repository was archived by the owner on Jul 1, 2025. It is now read-only.

Conversation

@tigerros
Copy link
Contributor

@tigerros tigerros commented Jun 19, 2025

Makes Visitor methods fallible (except for end_game). You can see why this is useful in action in the examples (particularly the new one, extract_fen). It makes error handling for users a lot cleaner.

Users who don't need error handling can simply use Infallible as the error type.

What happens after an error

The reader continues to parse the game even if the visitor errors, it just doesn't call any visitor methods afterwards. Early returns would be nice, but they corrupt the reader/split games. This means that there's no extra functionality in this PR, just a nicer API.

Example

Here's an example of an old way of handling fallible visitors:

struct NoFen(Result<NoFenInner, NoFenError>);

impl Visitor for NoFen {
    type Result = Result<NoFenOutput, NoFenError>;

    fn tag(&mut self, name: &[u8], _: RawTag<'_>) {
        let Ok(inner) = self.0 else { return; };

        if name == b"FEN" {
            self.0 = Err(NoFenError { ... });
            return;
        }

        // ...
    }

    fn san(&mut self, san: SanPlus) {
        let Ok(inner) = self.0 else { return; };
        // ...
    }

    fn end_game(&mut self) -> Self::Result {
        match self.0.as_mut() {
            Ok(inner) => Ok(inner.output()),
            // assuming NoFenError is not Copy
            Err(e) => Err(std::mem::replace(e, NoFenError::default())),
        }
    }
}

Alternative might be to store Option<NoFenError> and merge NoFenInner into NoFen.

Here's equivalent code with this PR:

struct NoFen { ... }

impl Visitor for NoFen {
    type Output = NoFenOutput;
    type Error = NoFenError;

    fn tag(&mut self, name: &[u8], _: RawTag<'_>) -> Result<(), Self::Error> {
        if name == b"FEN" {
            return Err(NoFenError { ... });
        }
        
        // ...
        Ok(())
    }

    fn san(&mut self, san: SanPlus) -> Result<(), Self::Error> {
        // ...
        Ok(())
    }

    fn end_game(&mut self) -> Self::Output {
        // output directly
    }
}

As you can see, it's a lot nicer.

@tigerros tigerros marked this pull request as ready for review June 24, 2025 16:42
@tigerros tigerros mentioned this pull request Jun 24, 2025
@tigerros
Copy link
Contributor Author

Moved to niklasf/shakmaty#104

@tigerros tigerros closed this Jun 28, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant