Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Deserializer.into_inner destructor #743

Merged
merged 1 commit into from
May 30, 2024

Conversation

dishmaker
Copy link
Contributor

@dishmaker dishmaker commented May 8, 2024

It's useful to extract position from Deserializer when error occurs.
Line and column can be extracted from inner reader without the need for RefCell inside a custom Cursor.

Other serde crate rmp_serde supports .into_inner()
https://docs.rs/rmp-serde/latest/rmp_serde/decode/struct.Deserializer.html#method.into_inner

pub fn from_str_xml<'de, T>(source: &'de str) -> eyre::Result<T>
where
    T: Deserialize<'de>,
{
    use quick_xml::de::Deserializer;
    let cur = Cursor::new(source);

    let mut de = Deserializer::from_reader(cur);
    let result = T::deserialize(&mut de);

    let cur: Cursor<&str> = de.into_inner().into_inner().into_inner();
    let object: T = result.wrap_err_with(|| format!("position: {}", cur.position()))?;

    Ok(object)
}

or even better:

    .wrap_err_with(|| {
        if let Some(before) = source.as_bytes().get(..cur.position() as usize) {
            let line_num = before.iter().filter(|&c| *c == b'\n').count() + 1;
            let line: &[u8] = before.rsplit(|e| *e == b'\n').next().unwrap_or(before);
            let col_num = line.len();
            format!("Ln {}, Col {}", line_num, col_num)
        }else{
            format!("position: {}", cur.position())
        }
        
    })?;

@Mingun
Copy link
Collaborator

Mingun commented May 8, 2024

Yes, nice addition. Could you also add a changelog entry? Some tests would be also good -- maybe add a doc example?

@codecov-commenter
Copy link

codecov-commenter commented May 8, 2024

Codecov Report

Attention: Patch coverage is 0% with 18 lines in your changes are missing coverage. Please review.

Project coverage is 61.12%. Comparing base (5d76174) to head (7a12fdf).
Report is 11 commits behind head on master.

Files Patch % Lines
src/de/mod.rs 0.00% 18 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #743      +/-   ##
==========================================
- Coverage   61.24%   61.12%   -0.13%     
==========================================
  Files          39       39              
  Lines       16277    16257      -20     
==========================================
- Hits         9969     9937      -32     
- Misses       6308     6320      +12     
Flag Coverage Δ
unittests 61.12% <0.00%> (-0.13%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Mingun Mingun added enhancement serde Issues related to mapping from Rust types to XML labels May 8, 2024
@dishmaker
Copy link
Contributor Author

Maybe let's add also .inner() method that returns &Reader

@dishmaker
Copy link
Contributor Author

I've added doc example and an example file

@dishmaker
Copy link
Contributor Author

cargo test works now.

@dishmaker
Copy link
Contributor Author

I hope addition of Reader.inner() function wasn't too big of a change.

@Mingun
Copy link
Collaborator

Mingun commented May 25, 2024

I modified your PR slightly, I hope I didn't lost something important:

  • squashed all commits
  • rename inner to get_ref to match the default Rust agreement (see standard library)
  • remove explicit inner_position tests, doctests is enough
  • remove example as it a slightly overburdened in my opinion (too complex types that is unnecessary to show the idea). The existing documentation should be enough

The two things remains about which I'm not sure yet:

  • It is really necessary to have .into_inner()? For the case of getting position the .get_ref() is enough. The danger with into_inner() is that by calling it, you will lose all events already read, but not yet used. If you use it to convert Deserializer to Reader after successful deserialization, you may get unexpected results. It would be better to work out this moment more carefully and not add this method yet.
  • I don't like that in order to get Reader from the Deserializer, you must call into_inner().into_inner(), or get_ref().get_ref(), or into_inner().get_ref(). It seems you will never need to get IoReader / SliceReader (result of the first into_inner() / get_ref()). We can rework this by moving [Slice/Io]Reader::into_inner() and get_ref() into XmlRead trait. See the first additional commit in my convert branch (it is based on that PR). From the other hand getting the intermediate [Slice/Io]Reader can help with the first problem, because IoReader can have destruction method which also would return inner buffer. Another consideration is that currently XmlRead is object-safe, but changes in convert will make it non-object-safe. I think this is fine, because anyway this trait is the implementation detail on which you should not depend

So, what do you think?

@dishmaker
Copy link
Contributor Author

dishmaker commented May 27, 2024

  • I think only get_ref is needed for now.
  • .get_ref().get_ref() pattern is common.
    For example in Rc<RefCell<()>>

@Mingun
Copy link
Collaborator

Mingun commented May 27, 2024

Ok, then I tend to keep only .get_ref() in their current implementation for now. .into_inner() can be added later if we find a good reason to have it. I'll make necessary changes at the end of week and now I want to wait if somebody else wants to add their thoughts.

@Mingun Mingun merged commit 42a91c9 into tafia:master May 30, 2024
6 checks passed
@dishmaker
Copy link
Contributor Author

❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement serde Issues related to mapping from Rust types to XML
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants